blob/0000755000176200001440000000000015131656566011206 5ustar liggesusersblob/tests/0000755000176200001440000000000015131116216012327 5ustar liggesusersblob/tests/testthat/0000755000176200001440000000000015131656566014210 5ustar liggesusersblob/tests/testthat/test-accessors.R0000644000176200001440000000727215131116216017264 0ustar liggesuserstest_that("subsetting blob returns blob", { x <- blob(!!!as.raw(1:5)) expect_s3_class(x[1], "blob") }) test_that("subsetting can return NA", { x <- blob(!!!as.raw(1:5)) expect_identical(x[NA_integer_], blob(NULL)) expect_identical(x[c(5, NA)], blob(as.raw(5L), NULL)) }) test_that("subset assignment works", { x <- blob(!!!as.raw(1:5)) x[3] <- blob(raw(1)) expect_identical(x, blob(!!!as.raw(c(1:2, 0L, 4:5)))) x[[4]] <- raw(1) expect_identical(x, blob(!!!as.raw(c(1:2, 0L, 0L, 5L)))) x[7] <- blob(raw(1)) expect_identical(x, blob(!!!as.raw(c(1:2, 0L, 0L, 5L)), NULL, raw(1))) }) test_that("can't insert objects of incorrect type", { x <- blob(!!!as.raw(1:5)) expect_error( x[[1]] <- 1, regexp = "Can't convert `value` to ", class = "vctrs_error_incompatible", fixed = TRUE ) expect_error( x[1] <- 1, regexp = "Can't convert `X[[i]]` to ", class = "vctrs_error_incompatible", fixed = TRUE ) }) test_that("can insert raw", { x <- blob(!!!as.raw(1:2)) x[[1]] <- as.raw(0) x[2] <- list(as.raw(0)) expect_equal(x, blob(as.raw(0), as.raw(0))) }) test_that("`[<-` can insert missing values", { # With `list(NULL)` x <- blob(raw(1), raw(2), raw(3)) x[c(1, 3)] <- list(NULL) expect_identical(x, blob(NULL, raw(2), NULL)) # With `blob(NULL)` x <- blob(raw(1), raw(2), raw(3)) x[c(1, 3)] <- blob(NULL) expect_identical(x, blob(NULL, raw(2), NULL)) }) test_that("`[<-` shrinks the blob when inserting literal `NULL`", { # Because is implemented on and inherits all list-like # qualities, for better or worse # `` method threw an incomprehensible error before this skip_if_not_installed("vctrs", "0.6.5.9000") x <- blob(raw(1), raw(2)) x[1] <- NULL expect_identical(x, blob(raw(2))) x <- blob(raw(1), raw(2), raw(3)) x[2:3] <- NULL expect_identical(x, blob(raw(1))) # By name x <- blob(a = raw(1), b = raw(2), c = raw(3)) x[c("b", "c")] <- NULL expect_identical(x, blob(a = raw(1))) # OOB x <- blob(raw(1)) x[2] <- NULL expect_identical(x, blob(raw(1))) }) test_that("`[[<-` shrinks the blob when inserting literal `NULL`", { # Because is implemented on and inherits all list-like # qualities, for better or worse # `` avoided shrinking the list before this, but we've changed that # to better align with base R lists skip_if_not_installed("vctrs", "0.6.5.9000") x <- blob(raw(1), raw(2)) x[[1]] <- NULL expect_identical(x, blob(raw(2))) x <- blob(a = raw(1), b = raw(2), c = raw(3)) x[["b"]] <- NULL expect_identical(x, blob(a = raw(1), c = raw(3))) # OOB x <- blob(raw(1)) x[[2]] <- NULL expect_identical(x, blob(raw(1))) }) test_that("`$<-` shrinks the blob when inserting literal `NULL`", { # Because is implemented on and inherits all list-like # qualities, for better or worse x <- blob(a = raw(1), b = raw(2), c = raw(3)) x$b <- NULL expect_identical(x, blob(a = raw(1), c = raw(3))) # OOB x <- blob(a = raw(1)) x$b <- NULL expect_identical(x, blob(a = raw(1))) }) test_that("can combine", { expect_identical( c(blob(raw(4), raw(5)), blob(raw(7))), blob(raw(4), raw(5), raw(7)) ) expect_identical( # Doesn't work with c() vec_c(list(raw(4), raw(5)), blob(raw(7))), blob(raw(4), raw(5), raw(7)) ) expect_identical( vec_c(list(raw(7)), blob(raw(4), raw(5)), list(raw(7))), blob(raw(7), raw(4), raw(5), raw(7)) ) expect_identical( vec_c(NA, blob()), blob(NULL) ) expect_identical( c(blob(), NA), blob(NULL) ) expect_error( c(blob(raw(4), raw(5)), raw(7)) ) expect_error( c(blob(raw(4), raw(5)), 7) ) }) blob/tests/testthat/test-format.R0000644000176200001440000000170215131116216016557 0ustar liggesusersexpect_format_equal <- function(formatted, result) { expect_equal( paste(formatted, collapse = "\n"), paste(result, collapse = "\n") ) } test_that("unequal sizes", { skip_on_cran() x <- blob(raw(2**2), raw(2**11), raw(2**20)) expect_format_equal( format(x), c( "blob[4 B]", "blob[2.05 kB]", "blob[1.05 MB]" ) ) expect_format_equal( format(x, trim = FALSE), c( "blob[ 4 B]", "blob[2.05 kB]", "blob[1.05 MB]" ) ) }) test_that("similar sizes", { skip_on_cran() x <- blob(raw(2**10), raw(2**11), raw(2**12)) expect_format_equal( format(x), c( "blob[1.02 kB]", "blob[2.05 kB]", "blob[4.10 kB]" ) ) }) test_that("empty", { x <- blob() expect_format_equal( format(x), character() ) }) test_that("output", { skip_on_cran() x <- blob(raw(2**2), raw(2**11), raw(2**20)) expect_known_output(print(x), "blob.txt") }) blob/tests/testthat/blob.txt0000644000176200001440000000007014224463610015650 0ustar liggesusers [1] blob[4 B] blob[2.05 kB] blob[1.05 MB] blob/tests/testthat/helper-deprecate.R0000644000176200001440000000006014210206472017520 0ustar liggesusers# scoped_lifecycle_errors(rlang::caller_env(8)) blob/tests/testthat/test-missing.R0000644000176200001440000000106615131116216016743 0ustar liggesuserstest_that("is.na detects nulls", { x <- blob(as.raw(1), NULL, as.raw(2), NULL) expect_equal(is.na(x), c(FALSE, TRUE, FALSE, TRUE)) }) test_that("is.na<- sets missing values", { x <- blob(!!!as.raw(1:4)) is.na(x) <- (1:4 %% 2 == 0) expect_equal(x, blob(as.raw(1), NULL, as.raw(3), NULL)) }) test_that("is.na<- auto-expansion for logical indexes", { x <- blob(!!!as.raw(1:4)) expect_error(is.na(x) <- rep(TRUE, 5)) }) test_that("is.na<- auto-expansion for character indices", { x <- blob(!!!as.raw(1:4)) expect_error(is.na(x) <- letters[1:2]) }) blob/tests/testthat/test-cast.R0000644000176200001440000000176015131116216016225 0ustar liggesuserstest_that("casting with as.blob()", { # Deprecated in v1.2.0 local_lifecycle_silence() expect_identical(as.blob(blob(raw(1))), blob(raw(1))) expect_identical(as.blob(list(raw(1))), blob(raw(1))) expect_identical(as.blob(raw(1)), blob(raw(1))) expect_identical(as.blob(1:3), blob(as.raw(1), as.raw(2), as.raw(3))) expect_identical( as.blob(c("abc", "def")), blob(charToRaw("abc"), charToRaw("def")) ) }) test_that("casting with as_blob()", { expect_identical(as_blob(blob(raw(1))), blob(raw(1))) expect_identical(as_blob(list(raw(1))), blob(raw(1))) expect_identical(as_blob(raw(1)), blob(raw(1))) expect_identical(blob(!!!as.raw(1:3)), blob(as.raw(1), as.raw(2), as.raw(3))) expect_identical( as_blob(c("abc", "def")), blob(charToRaw("abc"), charToRaw("def")) ) }) test_that("NA_character_ is converted to missing blob()", { expect_identical(as_blob(NA_character_), blob(NULL)) expect_identical(as_blob(c("1", NA_character_)), blob(as.raw(0x031), NULL)) }) blob/tests/testthat/test-construction.R0000644000176200001440000000035015131116216020017 0ustar liggesuserstest_that("input must be list of raw blobs", { # error from vctrs package expect_error(new_blob(1)) expect_error(blob(1), "must be a list of raw vectors") expect_error(blob(1, as.raw(1)), "must be a list of raw vectors") }) blob/tests/testthat.R0000644000176200001440000000060415131116216014312 0ustar liggesusers# This file is part of the standard setup for testthat. # It is recommended that you do not modify it. # # Where should you do additional test configuration? # Learn more about the roles of various files in: # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview # * https://testthat.r-lib.org/articles/special-files.html library(testthat) library(blob) test_check("blob") blob/MD50000644000176200001440000000256415131656566011525 0ustar liggesusers73d1425ea225a2684d2fbf3071944f08 *DESCRIPTION fc22d472c57070ab7425257e9105c1b3 *LICENSE 6d735311cb02c8484e5e25e7f8f0c17f *NAMESPACE 374588773439df609b2e7b942a083826 *NEWS.md d751353802b90f84f172cc4dfed90f69 *R/blob-package.R 50f2a1b78a9895983c1a5cad79e50ffd *R/blob.R 2d0374a307c3349e6cb2774b51c1c548 *R/cast.R bccc3a514de4e5275177ac6ba276fd94 *R/coerce.R 8ffdd476f6dbf9c3e43bfe8961d15294 *R/compat-lifecycle.R 0123aa2d5129c6b3f159b164eab223dc *R/format.R 6dd3a73c15682b8a0dd04515d9ce520f *R/prettyunits.R e8fbfbf8ace05ea7dbdff8da496b17d5 *R/util.R ee8319ef9d1ba02ee6a5eb4a4d8c3d98 *R/zzz.R 36ea1fb6de72b686341430b872ef37e0 *README.md 11835976f11cf847cd37841e91a04cbd *man/as.blob.Rd de0990e7f1ff7caf41e16a604a6a6306 *man/blob-package.Rd db4f3a3c39e1dbe8921e6c8dec375a54 *man/blob.Rd e5ebd9747daa786fb6a735bc9be0a805 *man/vec_cast.blob.Rd 5932c89be17465583d519b8de50811d5 *man/vec_ptype2.blob.Rd b8fce8135385d76606d8f721f5905d83 *tests/testthat.R 2b6213f9da53245378ad910526038003 *tests/testthat/blob.txt 9933209090f8600c0557dcedfd526f6d *tests/testthat/helper-deprecate.R 881a0955cd41def95043e5128d9df64c *tests/testthat/test-accessors.R 62507214da517f9e140a52a0be694d10 *tests/testthat/test-cast.R bd633547f91e1db20a1992f8e8e60e5b *tests/testthat/test-construction.R 283a4e1e5628fca40f223c57739e5288 *tests/testthat/test-format.R dfbbfc6f1f0f07f041c3ce5a63ce29fd *tests/testthat/test-missing.R blob/R/0000755000176200001440000000000015131116216011366 5ustar liggesusersblob/R/format.R0000644000176200001440000000175215131116216013006 0ustar liggesusers#' @export format.blob <- function(x, ...) { if (length(x) == 0) { return(character()) } ifelse(is.na(x), "", paste0("blob[", blob_size(x, ...), "]")) } #' @export obj_print_data.blob <- function(x, ...) { if (length(x) == 0) { return() } out <- stats::setNames(format(x), names(x)) print(out, quote = FALSE) invisible(x) } #' @export vec_ptype_abbr.blob <- function(x, ..., prefix_named, suffix_shape) { "blob" } #' @export vec_ptype_full.blob <- function(x, ...) { "blob" } blob_size <- function(x, digits = 3, trim = TRUE, ...) { x <- vapply(x, length, numeric(1)) if (isTRUE(trim)) { pretty_bytes_nopad(x) } else { pretty_bytes_default(x) } } # Dynamically exported, see zzz.R pillar_shaft.blob <- function(x, ...) { out <- ifelse( is.na(x), NA_character_, paste0( pillar::style_subtle("") ) ) pillar::new_pillar_shaft_simple(out, align = "right") } blob/R/coerce.R0000644000176200001440000000160215131116216012750 0ustar liggesusers#' Coercion #' #' Double dispatch methods to support [vctrs::vec_ptype2()]. #' #' @inheritParams vctrs::vec_ptype2 #' #' @method vec_ptype2 blob #' @export #' @export vec_ptype2.blob vec_ptype2.blob <- function(x, y, ..., x_arg = "", y_arg = "") { UseMethod("vec_ptype2.blob", y) } #' @method vec_ptype2.blob default #' @export vec_ptype2.blob.default <- function(x, y, ..., x_arg = "", y_arg = "") { vec_default_ptype2(x, y, x_arg = x_arg, y_arg = y_arg) } #' @method vec_ptype2.blob blob #' @export vec_ptype2.blob.blob <- function(x, y, ...) { new_blob(list()) } #' @method vec_ptype2.blob list #' @export vec_ptype2.blob.list <- function(x, y, ..., x_arg = "", y_arg = "") { check_raw_list(y, y_arg) new_blob(list()) } #' @method vec_ptype2.list blob #' @export vec_ptype2.list.blob <- function(x, y, ..., x_arg = "", y_arg = "") { check_raw_list(x, x_arg) new_blob(list()) } blob/R/zzz.R0000644000176200001440000000016414133350505012351 0ustar liggesusers# nocov start .onLoad <- function(...) { s3_register("pillar::pillar_shaft", "blob") invisible() } # nocov end blob/R/blob-package.R0000644000176200001440000000015415131116216014020 0ustar liggesusers#' @keywords internal "_PACKAGE" #' @import vctrs #' @import rlang #' @importFrom methods setOldClass NULL blob/R/cast.R0000644000176200001440000000254515131116216012451 0ustar liggesusers#' Casting #' #' Double dispatch methods to support [vctrs::vec_cast()]. #' #' @inheritParams vctrs::vec_cast #' #' @keywords internal #' @method vec_cast blob #' @export #' @export vec_cast.blob vec_cast.blob <- function(x, to, ...) UseMethod("vec_cast.blob") #' @method vec_cast.blob default #' @export vec_cast.blob.default <- function(x, to, ...) vec_default_cast(x, to, ...) #' @method vec_cast.blob blob #' @export vec_cast.blob.blob <- function(x, to, ...) x #' @method vec_cast.blob list #' @export vec_cast.blob.list <- function(x, to, ...) blob(!!!x) #' @method vec_cast.blob vctrs_list_of #' @export vec_cast.blob.vctrs_list_of <- function(x, to, ...) { new_blob(vec_cast(x, new_list_of(ptype = raw()))) } #' @method vec_cast.blob integer #' @export vec_cast.blob.integer <- function(x, to, ...) { signal_soft_deprecated( "Coercing an integer vector to a blob is deprecated, please coerce to a list first." ) blob(!!!lapply(x, as_single_raw)) } #' @method vec_cast.blob raw #' @export vec_cast.blob.raw <- function(x, to, ...) blob(x) #' @method vec_cast.blob character #' @export vec_cast.blob.character <- function(x, to, ...) { out <- as_blob(vector("list", length(x))) # charToRaw(NA_character_) == charToRaw("NA"), so only convert non-missing entries non_missing <- !is.na(x) out[non_missing] <- lapply(x[non_missing], charToRaw) out } blob/R/prettyunits.R0000644000176200001440000000236014210206472014125 0ustar liggesuserscompute_bytes <- function(bytes, smallest_unit = "B") { units0 <- c("B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") stopifnot( is.numeric(bytes), is.character(smallest_unit), length(smallest_unit) == 1, !is.na(smallest_unit), smallest_unit %in% units0 ) negative <- (bytes < 0) bytes <- abs(bytes) smallest_idx <- match(smallest_unit, units0) limits <- c(1000, 999950 * 1000^(seq_len(length(units0) - 2) - 1)) idx <- cut(bytes, c(0, limits, Inf), labels = FALSE, right = FALSE) idx <- pmax(idx, smallest_idx) amount <- bytes / signif(c(1, limits), 1)[idx] idx[is.na(idx)] <- smallest_idx unit <- units0[idx] data.frame( stringsAsFactors = FALSE, amount, unit, negative ) } pretty_bytes_default <- function(bytes) { szs <- compute_bytes(bytes) amt <- szs$amount * ifelse(szs$negative, -1, 1) is_int <- is.na(amt) | amt == as.integer(amt) ## String. For fractions we always show two fraction digits res <- ifelse( is_int, sprintf("%.0f%s", amt, ifelse(all(is_int) | (szs$unit == "B"), "", " ")), sprintf("%.2f", amt) ) format(paste(res, szs$unit), justify = "right") } pretty_bytes_nopad <- function(bytes) { sub("^\\s+", "", pretty_bytes_default(bytes)) } blob/R/compat-lifecycle.R0000644000176200001440000001403515131116216014734 0ustar liggesusers# nocov start --- compat-lifecycle # This file serves as a reference for currently unexported rlang # lifecycle functions. Please find the most recent version in rlang's # repository. These functions require rlang in your `Imports` # DESCRIPTION field but you don't need to import rlang in your # namespace. # Changelog # ========= # # 2021-04-19 # # - Removed `lifecycle()` function. You can now use the following in # your roxygen documentation to inline a badge: # # ``` # `r lifecycle::badge()` # ``` # # This is a build-time dependency on lifecycle so there is no need # to add lifecycle to Imports just to use badges. See also # `?usethis::use_lifecycle()` for importing or updating the badge # images in your package. # # - Soft-namespaced private objects. #' Signal deprecation #' #' @description #' #' These functions provide two levels of verbosity for deprecation #' warnings. #' #' * `signal_soft_deprecated()` warns only if called from the global #' environment (so the user can change their script) or from the #' package currently being tested (so the package developer can fix #' the package). #' #' * `warn_deprecated()` warns unconditionally. #' #' * `stop_defunct()` fails unconditionally. #' #' Both functions warn only once per session by default to avoid #' overwhelming the user with repeated warnings. #' #' @param msg The deprecation message. #' @param id The id of the deprecation. A warning is issued only once #' for each `id`. Defaults to `msg`, but you should give a unique ID #' when the message is built programmatically and depends on inputs. #' @param env The environment in which the soft-deprecated function #' was called. A warning is issued if called from the global #' environment. If testthat is running, a warning is also called if #' the retired function was called from the package being tested. #' #' @section Controlling verbosity: #' #' The verbosity of retirement warnings can be controlled with global #' options. You'll generally want to set these options locally with #' one of these helpers: #' #' * `with_lifecycle_silence()` disables all soft-deprecation and #' deprecation warnings. #' #' * `with_lifecycle_warnings()` enforces warnings for both #' soft-deprecated and deprecated functions. The warnings are #' repeated rather than signalled once per session. #' #' * `with_lifecycle_errors()` enforces errors for both #' soft-deprecated and deprecated functions. #' #' All the `with_` helpers have `scoped_` variants that are #' particularly useful in testthat blocks. #' #' @noRd NULL signal_soft_deprecated <- function(msg, id = msg, env = rlang::caller_env(2)) { msg <- .rlang_lifecycle_validate_message(msg) stopifnot( rlang::is_string(id), rlang::is_environment(env) ) if (rlang::is_true(rlang::peek_option("lifecycle_disable_warnings"))) { return(invisible(NULL)) } env_inherits_global <- function(env) { # `topenv(emptyenv())` returns the global env. Return `FALSE` in # that case to allow passing the empty env when the # soft-deprecation should not be promoted to deprecation based on # the caller environment. if (rlang::is_reference(env, emptyenv())) { return(FALSE) } rlang::is_reference(topenv(env), rlang::global_env()) } if ( rlang::is_true(rlang::peek_option("lifecycle_verbose_soft_deprecation")) || env_inherits_global(env) ) { warn_deprecated(msg, id) return(invisible(NULL)) } # Test for environment names rather than reference/contents because # testthat clones the namespace tested_package <- Sys.getenv("TESTTHAT_PKG") if ( nzchar(tested_package) && identical(Sys.getenv("NOT_CRAN"), "true") && rlang::env_name(topenv(env)) == rlang::env_name(rlang::ns_env(tested_package)) ) { warn_deprecated(msg, id) return(invisible(NULL)) } rlang::signal(msg, "lifecycle_soft_deprecated") } warn_deprecated <- function(msg, id = msg) { msg <- .rlang_lifecycle_validate_message(msg) stopifnot(rlang::is_string(id)) if (rlang::is_true(rlang::peek_option("lifecycle_disable_warnings"))) { return(invisible(NULL)) } if ( !rlang::is_true(rlang::peek_option("lifecycle_repeat_warnings")) && rlang::env_has(.rlang_lifecycle_deprecation_env, id) ) { return(invisible(NULL)) } rlang::env_poke(.rlang_lifecycle_deprecation_env, id, TRUE) has_colour <- function() rlang::is_installed("crayon") && crayon::has_color() silver <- function(x) if (has_colour()) crayon::silver(x) else x if (rlang::is_true(rlang::peek_option("lifecycle_warnings_as_errors"))) { .Signal <- stop_defunct } else { .Signal <- .Deprecated } if (!rlang::is_true(rlang::peek_option("lifecycle_repeat_warnings"))) { msg <- paste0( msg, "\n", silver("This warning is displayed once per session.") ) } .Signal(msg = msg) } .rlang_lifecycle_deprecation_env <- new.env(parent = emptyenv()) stop_defunct <- function(msg) { msg <- .rlang_lifecycle_validate_message(msg) err <- rlang::cnd( c("defunctError", "error", "condition"), old = NULL, new = NULL, package = NULL, message = msg ) stop(err) } local_lifecycle_silence <- function(frame = rlang::caller_env()) { rlang::local_options(.frame = frame, lifecycle_disable_warnings = TRUE) } with_lifecycle_silence <- function(expr) { local_lifecycle_silence() expr } local_lifecycle_warnings <- function(frame = rlang::caller_env()) { rlang::local_options( .frame = frame, lifecycle_disable_warnings = FALSE, lifecycle_verbose_soft_deprecation = TRUE, lifecycle_repeat_warnings = TRUE ) } with_lifecycle_warnings <- function(expr) { local_lifecycle_warnings() expr } local_lifecycle_errors <- function(frame = rlang::caller_env()) { local_lifecycle_warnings(frame = frame) rlang::local_options(.frame = frame, lifecycle_warnings_as_errors = TRUE) } with_lifecycle_errors <- function(expr) { local_lifecycle_errors() expr } .rlang_lifecycle_validate_message <- function(msg) { stopifnot(rlang::is_character(msg)) paste0(msg, collapse = "\n") } # nocov end blob/R/util.R0000644000176200001440000000043215131116216012465 0ustar liggesusersis_raw_list <- function(x) { if (!is.list(x)) { return(FALSE) } raw <- vapply(x, is.raw, logical(1)) null <- vapply(x, is.null, logical(1)) if (!all(raw | null)) { return(FALSE) } TRUE } as_single_raw <- function(x) { if (is.na(x)) NULL else as.raw(x) } blob/R/blob.R0000644000176200001440000000362115131116216012431 0ustar liggesuserssetOldClass(c("blob", "vctrs_list_of", "vctrs_vctr")) #' Construct a blob object #' #' `new_blob()` is a low-level constructor that takes a list of #' raw vectors. #' `blob()` constructs a blob from individual raw vectors. #' `as_blob()` and `is_blob()` are simple forwarders to [vctrs::vec_cast()] #' and [inherits()], respectively. #' #' @seealso [as.blob()] for the legacy interface for specifying casts. #' #' @param ... Individual raw vectors #' @param x A list of raw vectors, or other object to coerce #' @export #' @examples #' x1 <- charToRaw("Good morning") #' x2 <- as.raw(c(0x48, 0x65, 0x6c, 0x6c, 0x6f)) #' #' new_blob(list(x1, x2)) #' blob(x1, x2) #' #' as.blob(c("Good morning", "Good evening")) blob <- function(...) { x <- list2(...) validate_blob(x) new_blob(x) } #' @export #' @rdname blob new_blob <- function(x = list()) { new_list_of(x, ptype = raw(), class = "blob") } #' @export #' @rdname blob validate_blob <- function(x) { x_arg <- as_label(enexpr(x)) check_raw_list(x, x_arg) } check_raw_list <- function(x, x_arg) { if (!is_raw_list(x)) { stop("`", x_arg, "` must be a list of raw vectors", call. = FALSE) } } #' @export #' @rdname blob as_blob <- function(x) { vec_cast(x, new_blob()) } #' @export #' @rdname blob is_blob <- function(x) { vec_is(x, new_blob()) } #' Deprecated generic #' #' The `as.blob()` generic has been deprecated in favor of #' the [as_blob()] function (for users) and the [vec_cast.blob()] method #' (for implementers). #' Implement a `vec_cast.blob.myclass()` method to support #' coercing objects of your class to blobs. #' See [vctrs::vec_cast()] for more detail. #' #' @param x An object. #' @param ... Passed on to methods. #' #' @export #' @keywords internal as.blob <- function(x, ...) { signal_soft_deprecated("as.blob() is deprecated, use as_blob().") UseMethod("as.blob") } #' @export as.blob.default <- function(x, ...) { as_blob(x) } blob/NAMESPACE0000644000176200001440000000142514133350505012410 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(as.blob,default) S3method(format,blob) S3method(obj_print_data,blob) S3method(vec_cast,blob) S3method(vec_cast.blob,blob) S3method(vec_cast.blob,character) S3method(vec_cast.blob,default) S3method(vec_cast.blob,integer) S3method(vec_cast.blob,list) S3method(vec_cast.blob,raw) S3method(vec_cast.blob,vctrs_list_of) S3method(vec_ptype2,blob) S3method(vec_ptype2.blob,blob) S3method(vec_ptype2.blob,default) S3method(vec_ptype2.blob,list) S3method(vec_ptype2.list,blob) S3method(vec_ptype_abbr,blob) S3method(vec_ptype_full,blob) export(as.blob) export(as_blob) export(blob) export(is_blob) export(new_blob) export(validate_blob) export(vec_cast.blob) export(vec_ptype2.blob) import(rlang) import(vctrs) importFrom(methods,setOldClass) blob/LICENSE0000644000176200001440000000005214133350505012171 0ustar liggesusersYEAR: 2020 COPYRIGHT HOLDER: blob authors blob/NEWS.md0000644000176200001440000000405215131366317012275 0ustar liggesusers # blob 1.3.0 (2026-01-13) ## Testing - The upcoming vctrs update changes details on how subset assignment with `NULL` works. This motivated the minor version bump (@DavisVaughan, #65). ## Bug fixes - Fix argument consistency between S3 generics and methods. ## Chore - Upkeep (@MikeJohnPage, #55). # blob 1.2.4 (2023-03-17) ## Bug fixes - Fix argument consistency between S3 generics and methods. # blob 1.2.3 (2022-04-10) - `as_blob(NA_character_)` returns a missing `blob` instead of `as_blob("NA")` (#26, @michaelchirico). # blob 1.2.2 (2021-07-23) - Moved to "stable" lifecycle stage. - Remove `is_vector_s3()` (#19). # blob 1.2.1 - Inline prettyunits. - `vec_ptype2.hms.default()` forwards to `vec_default_ptype2()` for compatibility with vctrs 0.2.1. # blob 1.2.0 ## Breaking changes - The `blob` class is now based on `list_of(raw())` from the vctrs package (#11). This adds support for `vec_cast()` and `vec_ptype2()`. Some operations (such as subset assignment) are now stricter. The `new_blob()` constructor permits safe and fast construction of `blob` objects from a list, and `validate_blob()` checks an existing object for conformity with the rules. - The new `is_blob()` deprecates the existing `is.blob()`. `as.blob()` is deprecated in favor of `vec_cast()` or the new `as_blob()` (which is just a thin wrapper around `vec_cast()`). - Indexing a vector of blobs out of bounds now raises an error. Use `NA` as index to create a `NULL` blob. # blob 1.1.1 (2018-03-24) - Now suggesting *pillar* instead of importing *tibble*, and using colored formatting with the *prettyunits* package with `B` instead of `b` as units (#7, #9). - The blob class can now be used for S4 dispatch. - Calling `c()` on blob objects returns a blob. # blob 1.1.0 (2017-06-17) - New maintainer: Kirill Müller. - Added `as.blob.blob()`and `as.data.frame.blob()` methods (#3). - Size of very large blobs is displayed correctly. # blob 1.0.0 - Initial release. blob/README.md0000644000176200001440000000367315131116216012455 0ustar liggesusers [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) [![rcc](https://github.com/tidyverse/blob/workflows/rcc/badge.svg)](https://github.com/tidyverse/blob/actions) [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/blob)](https://cran.r-project.org/package=blob) [![Coverage Status](https://codecov.io/gh/tidyverse/blob/branch/main/graph/badge.svg)](https://app.codecov.io/gh/tidyverse/blob) # blob ## Overview The goal of blob is to provide a simple S3 class to represent a vector of binary objects, aka blobs. The `blob` class is a lightweight wrapper around a list of raw vectors, suitable for inclusion in a data frame. In most cases you will not need to use this package explicitly: it will be used transparently by packages that need to load BLOB columns from databases or binary file formats. ## Installation ``` r # The easiest way to get blob is to install the whole tidyverse: install.packages("tidyverse") # Alternatively, install just blob: install.packages("blob") # Or the development version from GitHub: # install.packages("pak") pak::pak("tidyverse/blob") ``` ## Example To create a blob, use `blob()`, `new_blob()` or `as_blob()`: ``` r library(blob) x1 <- charToRaw("Good morning") x2 <- as.raw(c(0x48, 0x65, 0x6c, 0x6c, 0x6f)) new_blob(list(x1, x2)) #> #> [1] blob[12 B] blob[5 B] blob(x1, x2) #> #> [1] blob[12 B] blob[5 B] as_blob(c("Good morning", "Good evening")) #> #> [1] blob[12 B] blob[12 B] ``` ------------------------------------------------------------------------ Please note that the ‘blob’ project is released with a [Contributor Code of Conduct](https://github.com/tidyverse/blob/blob/main/CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. blob/man/0000755000176200001440000000000015131116216011740 5ustar liggesusersblob/man/blob.Rd0000644000176200001440000000174114133350505013152 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{blob} \alias{blob} \alias{new_blob} \alias{validate_blob} \alias{as_blob} \alias{is_blob} \title{Construct a blob object} \usage{ blob(...) new_blob(x = list()) validate_blob(x) as_blob(x) is_blob(x) } \arguments{ \item{...}{Individual raw vectors} \item{x}{A list of raw vectors, or other object to coerce} } \description{ \code{new_blob()} is a low-level constructor that takes a list of raw vectors. \code{blob()} constructs a blob from individual raw vectors. \code{as_blob()} and \code{is_blob()} are simple forwarders to \code{\link[vctrs:vec_cast]{vctrs::vec_cast()}} and \code{\link[=inherits]{inherits()}}, respectively. } \examples{ x1 <- charToRaw("Good morning") x2 <- as.raw(c(0x48, 0x65, 0x6c, 0x6c, 0x6f)) new_blob(list(x1, x2)) blob(x1, x2) as.blob(c("Good morning", "Good evening")) } \seealso{ \code{\link[=as.blob]{as.blob()}} for the legacy interface for specifying casts. } blob/man/vec_cast.blob.Rd0000644000176200001440000000116314210206472014735 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/cast.R \name{vec_cast.blob} \alias{vec_cast.blob} \title{Casting} \usage{ \method{vec_cast}{blob}(x, to, ...) } \arguments{ \item{x}{Vectors to cast.} \item{to}{Type to cast to. If \code{NULL}, \code{x} will be returned as is.} \item{...}{For \code{vec_cast_common()}, vectors to cast. For \code{vec_cast()}, \code{vec_cast_default()}, and \code{vec_restore()}, these dots are only for future extensions and should be empty.} } \description{ Double dispatch methods to support \code{\link[vctrs:vec_cast]{vctrs::vec_cast()}}. } \keyword{internal} blob/man/as.blob.Rd0000644000176200001440000000120614133350505013550 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{as.blob} \alias{as.blob} \title{Deprecated generic} \usage{ as.blob(x, ...) } \arguments{ \item{x}{An object.} \item{...}{Passed on to methods.} } \description{ The \code{as.blob()} generic has been deprecated in favor of the \code{\link[=as_blob]{as_blob()}} function (for users) and the \code{\link[=vec_cast.blob]{vec_cast.blob()}} method (for implementers). Implement a \code{vec_cast.blob.myclass()} method to support coercing objects of your class to blobs. See \code{\link[vctrs:vec_cast]{vctrs::vec_cast()}} for more detail. } \keyword{internal} blob/man/blob-package.Rd0000644000176200001440000000157515131116216014546 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob-package.R \docType{package} \name{blob-package} \alias{blob-package} \title{blob: A Simple S3 Class for Representing Vectors of Binary Data ('BLOBS')} \description{ R's raw vector is useful for storing a single binary object. What if you want to put a vector of them in a data frame? The 'blob' package provides the blob object, a list of raw vectors, suitable for use as a column in data frame. } \seealso{ Useful links: \itemize{ \item \url{https://blob.tidyverse.org} \item \url{https://github.com/tidyverse/blob} \item Report bugs at \url{https://github.com/tidyverse/blob/issues} } } \author{ \strong{Maintainer}: Kirill Müller \email{kirill@cynkra.com} Authors: \itemize{ \item Hadley Wickham } Other contributors: \itemize{ \item RStudio [copyright holder, funder] } } \keyword{internal} blob/man/vec_ptype2.blob.Rd0000644000176200001440000000123614405016202015223 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/coerce.R \name{vec_ptype2.blob} \alias{vec_ptype2.blob} \title{Coercion} \usage{ \method{vec_ptype2}{blob}(x, y, ..., x_arg = "", y_arg = "") } \arguments{ \item{x, y}{Vector types.} \item{...}{These dots are for future extensions and must be empty.} \item{x_arg, y_arg}{Argument names for \code{x} and \code{y}. These are used in error messages to inform the user about the locations of incompatible types (see \code{\link[vctrs:stop_incompatible_type]{stop_incompatible_type()}}).} } \description{ Double dispatch methods to support \code{\link[vctrs:vec_ptype2]{vctrs::vec_ptype2()}}. } blob/DESCRIPTION0000644000176200001440000000231115131656566012711 0ustar liggesusersPackage: blob Title: A Simple S3 Class for Representing Vectors of Binary Data ('BLOBS') Version: 1.3.0 Authors@R: c( person("Hadley", "Wickham", role = "aut"), person("Kirill", "Müller", , "kirill@cynkra.com", role = "cre"), person("RStudio", role = c("cph", "fnd")) ) Description: R's raw vector is useful for storing a single binary object. What if you want to put a vector of them in a data frame? The 'blob' package provides the blob object, a list of raw vectors, suitable for use as a column in data frame. License: MIT + file LICENSE URL: https://blob.tidyverse.org, https://github.com/tidyverse/blob BugReports: https://github.com/tidyverse/blob/issues Imports: methods, rlang, vctrs (>= 0.2.1) Suggests: covr, crayon, pillar (>= 1.2.1), testthat (>= 3.0.0) Config/autostyle/scope: line_breaks Config/autostyle/strict: false Config/Needs/website: tidyverse/tidytemplate Config/testthat/edition: 3 Encoding: UTF-8 RoxygenNote: 7.3.3.9000 NeedsCompilation: no Packaged: 2026-01-13 06:57:54 UTC; kirill Author: Hadley Wickham [aut], Kirill Müller [cre], RStudio [cph, fnd] Maintainer: Kirill Müller Repository: CRAN Date/Publication: 2026-01-14 09:10:14 UTC