Nothing
#' Build code to recreate an object from its serialized form
#'
#' `construct_serialize()` creates code that reconstructs an R object by serializing
#' it to raw bytes and then calling `unserialize()`. This is a fallback method that
#' works for almost any R object, including those that are difficult or impossible
#' to construct idiomatically.
#'
#' @details
#'
#' This function generates code in the form:
#' ```r
#' unserialize(as.raw(c(
#' # --- HEADER ---
#' c(0x58, 0x0a, ...),
#' # --- DATA ---
#' c(0x00, 0x00, ...)
#' )))
#' ```
#'
#' The generated code includes detailed comments explaining the binary structure,
#' making it useful for understanding R's serialization format.
#'
#' ## Limitations
#'
#' `construct_serialize()` reproduces faithfully what `serialize()` does, so it
#' shares its limitations. Some objects don't survive serialization or can be
#' restored only in some conditions:
#' - **External pointers**: The address is lost, we get a null pointer
#' - **Weak references**: The key and value are lost
#' - **Connections**: Only the connection number is stored, the reconstructed
#' object is valid only in the same session, as long as the connection is open
#' - **Namespaces and package environments**: They are stored by name, so the
#' package must be available when the code is run
#'
#' The function is designed for small objects, every byte is documented so the
#' output is long and large objects (hundreds of kilobytes once serialized) are
#' slow to process. Note that functions defined in a file keep a reference to
#' the whole file through their srcref, use `utils::removeSource()` to get rid of it.
#'
#' @param x An R object to serialize and reconstruct.
#' @param collapse_header Logical. If `TRUE`, the serialization header is displayed
#' as a single collapsed line (`c(0x58, 0x0a, ..., 0x38)`). If `FALSE` (default),
#' the header is displayed with detailed comments explaining each component.
#'
#' @return An object of class `"constructive_code"` containing the generated code
#' as a character vector. Each element is one line of code.
#'
#' @seealso [construct()] for idiomatic object construction, [serialize()] for
#' the underlying serialization mechanism.
#'
#' @export
#' @examples
#' # Simple objects
#' construct_serialize(1:5)
#' construct_serialize(c("hello", "world"))
#'
#' # Complex objects
#' construct_serialize(data.frame(a = 1:3, b = letters[1:3]))
#' construct_serialize(matrix(1:6, nrow = 2))
#'
#' # Objects with attributes
#' x <- c(a = 1, b = 2, c = 3)
#' construct_serialize(x)
#'
#' # Expressions and calls
#' construct_serialize(quote(mean(x)))
#' construct_serialize(expression(x + 1, y * 2))
#'
#' # Special values
#' construct_serialize(c(NA, NaN, Inf, -Inf))
#'
#' # Builtin functions
#' construct_serialize(sum)
#' construct_serialize(`if`)
#'
#' # The generated code can be evaluated to reconstruct the object
#' code <- construct_serialize(iris)
#' reconstructed <- eval(parse(text = paste(code, collapse = "\n")))
#' identical(reconstructed, iris)
construct_serialize <- function(x, collapse_header = FALSE) {
# 1. Convert input object to a raw vector
raw_vector <- serialize(x, connection = NULL, ascii = FALSE)
# 2. Process the header part of the raw vector
header_res <- serialize_header(raw_vector, collapse = collapse_header)
# 3. Process the data part of the raw vector
# the reference table is filled as we meet symbols, environments etc
globals[["serialize_refs"]] <- character(0)
data_res <- serialize_data(header_res$x, header_res$i)
# all bytes should be consumed, no more no less
if (length(data_res$x) > 0 || data_res$i != length(raw_vector) + 1) {
abort(sprintf(
"Internal error: parsed %s bytes out of %s, please report this issue",
data_res$i - 1, length(raw_vector)
))
}
# 4. Trim the final trailing comma from each block of code
# (trim_last_comma is defined in utils.R)
data_code <- trim_last_comma(data_res$code)
# 5. Combine the generated code parts, matching the example style
if (collapse_header) {
# Header is already a single collapsed line
code <- c(
"# --- HEADER ---",
paste0("c(", header_res$code, "),"),
"# --- DATA ---",
"c(",
paste0(" ", data_code),
")"
)
} else {
header_code <- trim_last_comma(header_res$code)
code <- c(
"# --- HEADER ---",
"c(",
paste0(" ", header_code),
"),",
"# --- DATA ---",
"c(",
paste0(" ", data_code),
")"
)
}
# 6. Format the code into a single string and wrap it
code <- c(
"unserialize(as.raw(c(",
paste0(" ", code),
")))"
)
code <- structure(code, class = "constructive_code")
return(code)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.