#' Load the instance back from \code{\link{xgb.serialize}}
#'
#' @param buffer the buffer containing booster instance saved by \code{\link{xgb.serialize}}
#' @param handle An \code{xgb.Booster.handle} object which will be overwritten with
#' the new deserialized object. Must be a null handle (e.g. when loading the model through
#' `readRDS`). If not provided, a new handle will be created.
#' @return An \code{xgb.Booster.handle} object.
#'
#' @export
xgb.unserialize <- function(buffer, handle = NULL) {
  cachelist <- list()
  if (is.null(handle)) {
    handle <- .Call(XGBoosterCreate_R, cachelist)
  } else {
    if (!is.null.handle(handle))
      stop("'handle' is not null/empty. Cannot overwrite existing handle.")
    .Call(XGBoosterCreateInEmptyObj_R, cachelist, handle)
  }
  tryCatch(
    .Call(XGBoosterUnserializeFromBuffer_R, handle, buffer),
    error = function(e) {
      error_msg <- conditionMessage(e)
      m <- regexec("(src[\\\\/]learner.cc:[0-9]+): Check failed: (header == serialisation_header_)",
                   error_msg, perl = TRUE)
      groups <- regmatches(error_msg, m)[[1]]
      if (length(groups) == 3) {
        warning(paste("The model had been generated by XGBoost version 1.0.0 or earlier and was ",
                      "loaded from a RDS file. We strongly ADVISE AGAINST using saveRDS() ",
                      "function, to ensure that your model can be read in current and upcoming ",
                      "XGBoost releases. Please use xgb.save() instead to preserve models for the ",
                      "long term. For more details and explanation, see ",
                      "https://xgboost.readthedocs.io/en/latest/tutorials/saving_model.html",
                      sep = ""))
        .Call(XGBoosterLoadModelFromRaw_R, handle, buffer)
      } else {
        stop(e)
      }
    })
  class(handle) <- "xgb.Booster.handle"
  return (handle)
}
