Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependencies #2

Merged
merged 7 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.Rproj.user
src/rust/vendor
src/vendor
docs
9 changes: 3 additions & 6 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: b64
Title: Fast and Vectorized Base 64 Engine
Version: 0.1.0
Version: 0.1.0.9000
Authors@R:
person("Josiah", "Parry", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0001-9910-865X"))
etiennebacher marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -14,13 +14,10 @@ License: MIT + file LICENSE
Encoding: UTF-8
Language: en
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.0
Config/rextendr/version: 0.3.1.9000
SystemRequirements: Cargo (Rust's package manager), rustc
Imports:
blob,
cli,
rlang
Suggests:
blob,
testthat (>= 3.0.0)
Config/testthat/edition: 3
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ export(engine)
export(new_alphabet)
export(new_config)
export(new_engine)
importFrom(blob,blob)
useDynLib(b64, .registration = TRUE)
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# b64 (development version)

* All hard dependencies were removed (#2, @etiennebacher).

# b64 0.1.0

* Initial CRAN submission.
11 changes: 5 additions & 6 deletions R/alphabet.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
#' new_alphabet("qwertyuiop[]asdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890")
#' @returns an object of class `alphabet`
alphabet <- function(which = "standard") {
rlang::arg_match(
match.arg(
which,
values = c("standard", "bcrypt", "bin_hex", "crypt", "imap_mutf7", "url_safe")
choices = c("standard", "bcrypt", "bin_hex", "crypt", "imap_mutf7", "url_safe")
)
structure(alphabet_(which), class = "alphabet")
}
Expand All @@ -42,10 +42,9 @@ alphabet <- function(which = "standard") {
new_alphabet <- function(chars) {
n <- nchar(chars)
if (nchar(chars) != 64) {
cli::cli_abort(
c(
"{.arg chars} must be 64 unique characters",
"i" = "{n} characters provided"
stop(
paste(
"`chars` must contain 64 unique characters. Only", n, "characters were provided."
)
)
}
Expand Down
1 change: 0 additions & 1 deletion R/b64-package.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#' @keywords internal
#' @importFrom blob blob
"_PACKAGE"

## usethis namespace: start
Expand Down
4 changes: 2 additions & 2 deletions R/config.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ new_config <- function(
decode_padding_mode = c("canonical", "indifferent", "none")
) {

padding_mode <- rlang::arg_match0(
padding_mode <- match.arg(
decode_padding_mode,
values = c("canonical", "indifferent", "none")
choices = c("canonical", "indifferent", "none")
)

res <- new_config_(
Expand Down
4 changes: 2 additions & 2 deletions R/encode.R
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ decode <- function(what, eng = engine()) {
#' @name encode
encode_file <- function(path, eng = engine()) {
if (!file.exists(path)) {
cli::cli_abort("{.arg path} does not exist")
stop(paste0("`", path, "` does not exist"))
}

encode_file_(path, eng)
Expand All @@ -56,7 +56,7 @@ encode_file <- function(path, eng = engine()) {
#' @rdname encode
decode_file <- function(path, eng = engine()) {
if (!file.exists(path)) {
cli::cli_abort("{.arg path} does not exist")
stop(paste0("`", path, "` does not exist"))
}

decode_file_(path, eng)
Expand Down
22 changes: 11 additions & 11 deletions R/engine.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,26 @@
#' new_engine(alphabet("bcrypt"), new_config())
engine <- function(which = "standard") {
provided <- c("standard", "standard_no_pad", "url_safe", "url_safe_no_pad")
rlang::arg_match0(which, provided)
match.arg(which, choices = provided)
structure(engine_(which), class = "engine")
}

#' @export
#' @rdname engine
new_engine <- function(.alphabet = alphabet(), .config = new_config()) {

if (!rlang::inherits_only(.alphabet, "alphabet")) {
cli::cli_abort(
c(
"{.arg .alphabet} is not an object of class {.cls alphabet}",
"*" = "use {.fn alphabet} for a standard base64 alphabet"
if (!inherits(.alphabet, "alphabet")) {
stop(
paste(
"`.alphabet` is not an object of class 'alphabet'.\n" ,
"Use `alphabet()` for a standard base64 alphabet."
)
)
} else if (!rlang::inherits_only(.config, "engine_config")) {
cli::cli_abort(
c(
"{.arg config} is not a {.cls engine_config} object",
"*" = "create one with {.fn new_config}"
} else if (!inherits(.config, "engine_config")) {
stop(
paste(
"`.config` is not an object of class 'engine_config'.\n" ,
"Create one with `new_config()`."
)
)
}
Expand Down
2 changes: 0 additions & 2 deletions R/extendr-wrappers.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ print_config_ <- function(config) .Call(wrap__print_config_, config)
#' chunked
#'
#' b64_wrap(chunked, "\n")
#'
#'
#' @param width a numeric scalar defining the width of the chunks. Must be divisible by 4.
#' @param encoded a character vector of base64 encoded strings.
#' @export
Expand Down
66 changes: 46 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

<!-- README.md is generated from README.Rmd. Please edit that file -->

# b64
# b64 <img src="man/figures/logo.svg" align="right" height="139" alt="" />

<!-- badges: start -->

Expand Down Expand Up @@ -36,8 +36,11 @@ Decode using `decode()`
``` r
decoded <- decode(hello)
decoded
#> <blob[1]>
#> [1] blob[19 B]
#> [[1]]
#> [1] 48 65 6c 6c 6f 2c 20 66 72 6f 6d 20 65 78 74 65 6e 64 72
#>
#> attr(,"class")
#> [1] "blob" "vctrs_list_of" "vctrs_vctr" "list"
```

We can convert the decoded base64 to characters and see how it worked.
Expand All @@ -54,28 +57,50 @@ Both `encode()` and `decode()` are vectorized.
``` r
lorem <- unlist(lorem::ipsum(5, 1, 5))
lorem
#> [1] "Sit ligula senectus litora viverra consequat."
#> [2] "Consectetur vulputate vivamus sapien a ridiculus porta."
#> [3] "Ipsum orci cras posuere lacus."
#> [4] "Lorem nostra hendrerit nascetur vel duis consequat."
#> [5] "Adipiscing dui blandit vestibulum bibendum?"
#> [1] "Dolor malesuada cursus faucibus facilisi accumsan viverra?"
#> [2] "Sit penatibus lobortis at aptent pellentesque!"
#> [3] "Sit euismod accumsan semper ante cubilia nam velit himenaeos!"
#> [4] "Lorem pulvinar augue aliquam!"
#> [5] "Dolor nullam facilisi senectus penatibus."

encoded <- encode(lorem)
encoded
#> [1] "U2l0IGxpZ3VsYSBzZW5lY3R1cyBsaXRvcmEgdml2ZXJyYSBjb25zZXF1YXQu"
#> [2] "Q29uc2VjdGV0dXIgdnVscHV0YXRlIHZpdmFtdXMgc2FwaWVuIGEgcmlkaWN1bHVzIHBvcnRhLg=="
#> [3] "SXBzdW0gb3JjaSBjcmFzIHBvc3VlcmUgbGFjdXMu"
#> [4] "TG9yZW0gbm9zdHJhIGhlbmRyZXJpdCBuYXNjZXR1ciB2ZWwgZHVpcyBjb25zZXF1YXQu"
#> [5] "QWRpcGlzY2luZyBkdWkgYmxhbmRpdCB2ZXN0aWJ1bHVtIGJpYmVuZHVtPw=="
#> [1] "RG9sb3IgbWFsZXN1YWRhIGN1cnN1cyBmYXVjaWJ1cyBmYWNpbGlzaSBhY2N1bXNhbiB2aXZlcnJhPw=="
#> [2] "U2l0IHBlbmF0aWJ1cyBsb2JvcnRpcyBhdCBhcHRlbnQgcGVsbGVudGVzcXVlIQ=="
#> [3] "U2l0IGV1aXNtb2QgYWNjdW1zYW4gc2VtcGVyIGFudGUgY3ViaWxpYSBuYW0gdmVsaXQgaGltZW5hZW9zIQ=="
#> [4] "TG9yZW0gcHVsdmluYXIgYXVndWUgYWxpcXVhbSE="
#> [5] "RG9sb3IgbnVsbGFtIGZhY2lsaXNpIHNlbmVjdHVzIHBlbmF0aWJ1cy4="
```

We can decode all of these using `decode()` as well. This will always
return a `blob` object.
etiennebacher marked this conversation as resolved.
Show resolved Hide resolved

``` r
decode(encoded)
#> <blob[5]>
#> [1] blob[45 B] blob[55 B] blob[30 B] blob[51 B] blob[43 B]
#> [[1]]
#> [1] 44 6f 6c 6f 72 20 6d 61 6c 65 73 75 61 64 61 20 63 75 72 73 75 73 20 66 61
#> [26] 75 63 69 62 75 73 20 66 61 63 69 6c 69 73 69 20 61 63 63 75 6d 73 61 6e 20
#> [51] 76 69 76 65 72 72 61 3f
#>
#> [[2]]
#> [1] 53 69 74 20 70 65 6e 61 74 69 62 75 73 20 6c 6f 62 6f 72 74 69 73 20 61 74
#> [26] 20 61 70 74 65 6e 74 20 70 65 6c 6c 65 6e 74 65 73 71 75 65 21
#>
#> [[3]]
#> [1] 53 69 74 20 65 75 69 73 6d 6f 64 20 61 63 63 75 6d 73 61 6e 20 73 65 6d 70
#> [26] 65 72 20 61 6e 74 65 20 63 75 62 69 6c 69 61 20 6e 61 6d 20 76 65 6c 69 74
#> [51] 20 68 69 6d 65 6e 61 65 6f 73 21
#>
#> [[4]]
#> [1] 4c 6f 72 65 6d 20 70 75 6c 76 69 6e 61 72 20 61 75 67 75 65 20 61 6c 69 71
#> [26] 75 61 6d 21
#>
#> [[5]]
#> [1] 44 6f 6c 6f 72 20 6e 75 6c 6c 61 6d 20 66 61 63 69 6c 69 73 69 20 73 65 6e
#> [26] 65 63 74 75 73 20 70 65 6e 61 74 69 62 75 73 2e
#>
#> attr(,"class")
#> [1] "blob" "vctrs_list_of" "vctrs_vctr" "list"
```

## Encoding and decoding files
Expand All @@ -99,8 +124,8 @@ bench::mark(
#> # A tibble: 2 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 b64 39.8ms 41.3ms 24.0 24MB 0
#> 2 base64enc 112.1ms 115.2ms 8.56 66.5MB 17.1
#> 1 b64 76.9ms 79.8ms 12.6 24.1MB 0
#> 2 base64enc 189ms 199.7ms 5.07 66.9MB 10.1
```

While the encoding is very impressive, better yet is the decoding
Expand All @@ -122,8 +147,8 @@ bench::mark(
#> # A tibble: 2 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 b64 16.1ms 16.8ms 56.1 18MB 9.34
#> 2 base64enc 209.1ms 210.7ms 4.75 18MB 0
#> 1 b64 46ms 47.1ms 21.2 18.1MB 5.30
#> 2 base64enc 308ms 314.1ms 3.18 18.1MB 0
```

## Alternative engines
Expand Down Expand Up @@ -153,7 +178,8 @@ We can use our new engine to decode it.
``` r
decode(url_safe_encoded, url_engine)
#> <blob[1]>
#> [1] blob[4 B]
#> [[1]]
#> [1] fa ec 20 55
```

### Custom Engines
Expand Down
5 changes: 3 additions & 2 deletions man/b64-package.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions man/utils.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 4 additions & 9 deletions src/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,9 @@ fn encode_vectorized_(what: Either<Strings, List>, engine: Robj) -> Strings {
})
.collect::<Strings>(),
Either::Right(r) => {
if !r.inherits("blob") {
throw_r_error("Expected a character vector or an object of class `blob`")
}

r.into_iter()
.map(|(_, b)| {
if b.is_null() {
if !b.inherits("raw") | b.is_null() {
Rstr::na()
} else {
let raw: Raw = b.try_into().unwrap();
Expand Down Expand Up @@ -195,12 +191,11 @@ fn decode_vectorized_(what: Either<Strings, List>, engine: Robj) -> Robj {
.set_class(&["blob", "vctrs_list_of", "vctrs_vctr", "list"])
.unwrap(),
Either::Right(r) => {
if !r.inherits("blob") {
throw_r_error("Expected a character vector or an object of class `blob`")
}
r.into_iter()
.map(|(_, b)| {
if b.is_null() {
if !b.inherits("raw") {
Rstr::na().into_robj()
} else if b.is_null() {
().into_robj()
} else {
let raw: Raw = b.try_into().unwrap();
etiennebacher marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading