## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

## ----setup--------------------------------------------------------------------
library(fluffy)

## ----schema example, eval=FALSE-----------------------------------------------
# list(
#   type = "data.frame",
#   id = list(
#     type = "numeric"
#   ),
#   email = list(
#     type = "character",
#     regex = "@gmail.com$"
#   ),
#   list(
#     min_length = 2
#   )
# )

## ----1 level above basic example, echo = FALSE--------------------------------
lobstr::tree(list(
  "Top level rule" = "Applied to `data`.",
  list(
    "Depth 1 rule" = "Applied to `data[[1]]`.",
    list(
      "Depth 2 rule" = "Applied to `data[[1]][[1]]`."
    )
  )
))

## ----1 level above basic named example, echo = FALSE--------------------------
lobstr::tree(list(
  "Top level rule" = "Applied to `data`.",
  "x" = list(
    "Depth 1 rule" = "Applied to `data[['x']]`.",
    "x" = list(
      "Depth 2 rule" = "Applied to `data[['x']][['x']]`."
    )
  )
))

## ----1 level above deeply nested example, echo = FALSE------------------------
lobstr::tree(list(list(list(list("Applied to `data[[1]][[1]][[1]]`.")))))

## ----double hit example-------------------------------------------------------
Validator(
  data = list(x = 1L),
  schema = list(
    list(type = "integer"), # matched positionally
    x = list(type = "character") # matched by name to same element
  )
)@errors

## ----rule order---------------------------------------------------------------
r <- Registry()
r@control_rules
r@transform_rules
r@validate_rules

Schema(
  list(
    min_length = 2L,
    type = "integer",
    default = 10L,
    coerce = "double"
  )
)@schema

## ----rule order edited--------------------------------------------------------
r <- Registry()
r@validate_rules <- c("min_length", r@validate_rules[!grepl("min_length", r@validate_rules)])

Schema(
  schema = list(
    min_length = 2L,
    type = "integer",
    default = 10L,
    coerce = "double"
  ),
  registry = r
)@schema

## ----str2func example---------------------------------------------------------
r <- Registry()
r@str_to_fn_rules

r@str_to_fn_converter

Schema(
  list(predicate = "function(x) x > 10")
)@schema

## ----schema errors example----------------------------------------------------
Schema(
  list(
    type = "not a type",
    list(apply = 1),
    list(type = "character"),
    list(a = list(min_length = function(x) x + 1))
  )
)@errors

## ----schema validation, error=TRUE--------------------------------------------
try({
Schema(
  list(
    x = list(type = "character"),
    x = list(type = "integer"),
    list("character"),
    list(my_rule = 1L)
  ),
  error = TRUE
)
})

## ----schema rule validation, error=TRUE---------------------------------------
try({
Schema(
  list(
    predicate = 1L,
    dependency = 1.5
  ),
  error = TRUE
)
})

## ----cross rule example, error=TRUE-------------------------------------------
try({
Schema(
  list(
    min_val = 5,
    max_val = 1
  ),
  error = TRUE
)
})

## ----evaluation order example, eval=FALSE-------------------------------------
# recursive_walk <- function(lst) {
#   for (i in seq_along(lst)) {
#     if (!is.list(lst[[i]])) {
#       # do rule...
#     } else {
#       # recurse into list node...
#       lst[[i]] <- recursive_walk(lst[[i]])
#     }
#   }
#   lst
# }

## ----transformed elements example---------------------------------------------
s <- Schema(
  list(
    list(
      apply = "function(x, .data, ...) if (.data[[2]] == 1) x + 1"
    ),
    list(
      apply = "function(x, .data, ...) if (.data[[2]] == 0) x + 1"
    ),
    list(
      apply = "function(x, .data, ...) if (.data[[2]] == 1) x + 2"
    ),
    list(
      apply = "function(x, .data, ...) if (.data[[3]] == 2) x + 3"
    )
  )
)

Validator(c(0, 0, 0, 0), s)@data

## ----validator errors example-------------------------------------------------
Validator(
  data = list(a = 1, b = 2),
  schema = list(
    type = "double",
    a = list(type = "character"),
    list(type = "array")
  )
)@errors

## ----validator error message example, error=TRUE------------------------------
try({
Validator(
  data = list(a = 1, b = 2),
  schema = list(
    type = "double",
    a = list(type = "character"),
    list(type = "array")
  ),
  error = TRUE
)
})

## ----validator invalid schema example, error=TRUE-----------------------------
try({
v <- Validator(1L, list(type = "not a type"))
v@errors
v@Schema@errors

Validator(1L, list(type = "not a type"), error = TRUE)
})

## ----yaml validation example, error=TRUE--------------------------------------
try({
yaml_schema <- yaml::yaml.load(
  "
  type: 'list'
  a:
    type: 'character'
  b:
    type: 'list'
    a:
      type: 'numeric'
    b:
      type: 'character'
      min_nchar: 3
  "
)

yaml_data <- yaml::yaml.load(
  "
  a: 1
  b:
    a: 1
    b: 'Hi'
  "
)

Validator(yaml_data, yaml_schema, error = TRUE)
})

## ----json validation example, error=TRUE--------------------------------------
try({
json_schema <- jsonlite::fromJSON(
  '{
    "type": "list",
    "a": {
      "type": "numeric",
      "min_length": 2
    },
    "b": {
      "type": "list",
      "a": {
        "type": "numeric",
        "max_val": 5
      },
      "b": {
        "type": "character"
      }
    }
  }'
)

json_data <- jsonlite::fromJSON(
  '{
    "a": 1,
    "b": {
      "a": 10,
      "b": "Hi"
    }
  }'
)

Validator(json_data, json_schema, error = TRUE)
})

## ----rect validation example, error=TRUE--------------------------------------
try({
# rectangular data, from `readr` readme
# works for any data.frame data, e.g., sav, dta, xls, xlsx, csv, tsv, etc.
rect_schema <- list(
  type = "data.frame",
  chicken = list(type = "character", nzchar = TRUE),
  sex = list(coerce = "factor", levels = c("rooster", "hen")),
  eggs_laid = list(type = "integer", positive = TRUE),
  motto = list(type = "character", nzchar = TRUE)
)

rect_data <- readr::read_csv(
  readr::readr_example("chickens.csv"),
  show_col_types = FALSE
)

Validator(rect_data, rect_schema, error = TRUE)
})

## ----any R object example, error=TRUE-----------------------------------------
try({
Validator(
  call("mean", 1:10),
  list(
    type = "call",
    list(type = "name"),
    list(predicate = "function(x) identical(x, 1:10)")
  )
)@valid
Validator(expression(x + 1), list(type = "expression"))@valid
Validator(table(x = 1), list(type = "table"))@valid
Validator(new.env(), list(type = "environment"))@valid
e <- new.env()
e$a <- 1L
e$b <- "Hi"
Validator(
  e,
  list(
    type = "environment",
    a = list(type = "integer"),
    b = list(type = "character")
  )
)@valid
})

