# The following bytes have significant meaning in JSON
const BACKSPACE     = UInt8('\b')
const TAB           = UInt8('\t')
const NEWLINE       = UInt8('\n')
const FORM_FEED     = UInt8('\f')
const RETURN        = UInt8('\r')
const SPACE         = UInt8(' ')
const STRING_DELIM  = UInt8('"')
const PLUS_SIGN     = UInt8('+')
const DELIMITER     = UInt8(',')
const MINUS_SIGN    = UInt8('-')
const DECIMAL_POINT = UInt8('.')
const SOLIDUS       = UInt8('/')
const DIGIT_ZERO    = UInt8('0')
const DIGIT_NINE    = UInt8('9')
const SEPARATOR     = UInt8(':')
const LATIN_UPPER_A = UInt8('A')
const LATIN_UPPER_E = UInt8('E')
const LATIN_UPPER_F = UInt8('F')
const LATIN_UPPER_I = UInt8('I')
const LATIN_UPPER_N = UInt8('N')
const ARRAY_BEGIN   = UInt8('[')
const BACKSLASH     = UInt8('\\')
const ARRAY_END     = UInt8(']')
const LATIN_A       = UInt8('a')
const LATIN_B       = UInt8('b')
const LATIN_E       = UInt8('e')
const LATIN_F       = UInt8('f')
const LATIN_I       = UInt8('i')
const LATIN_L       = UInt8('l')
const LATIN_N       = UInt8('n')
const LATIN_R       = UInt8('r')
const LATIN_S       = UInt8('s')
const LATIN_T       = UInt8('t')
const LATIN_U       = UInt8('u')
const LATIN_Y       = UInt8('y')
const OBJECT_BEGIN  = UInt8('{')
const OBJECT_END    = UInt8('}')

const ESCAPES = Dict(
	STRING_DELIM => STRING_DELIM,
	BACKSLASH    => BACKSLASH,
	SOLIDUS      => SOLIDUS,
	LATIN_B      => BACKSPACE,
	LATIN_F      => FORM_FEED,
	LATIN_N      => NEWLINE,
	LATIN_R      => RETURN,
	LATIN_T      => TAB)

const REVERSE_ESCAPES = Dict(reverse(p) for p in ESCAPES)
const ESCAPED_ARRAY = Vector{Vector{UInt8}}(undef, 256)
for c in 0x00:0xFF
	ESCAPED_ARRAY[c+1] = if c == SOLIDUS
		[SOLIDUS]  # don't escape this one
	elseif c â‰¥ 0x80
		[c]  # UTF-8 character copied verbatim
	elseif haskey(REVERSE_ESCAPES, c)
		[BACKSLASH, REVERSE_ESCAPES[c]]
	elseif iscntrl(Char(c)) || !isprint(Char(c))
		UInt8[BACKSLASH, LATIN_U, string(c, base = 16, pad = 4)...]
	else
		[c]
	end
end

export BACKSPACE, TAB, NEWLINE, FORM_FEED, RETURN, SPACE, STRING_DELIM,
	PLUS_SIGN, DELIMITER, MINUS_SIGN, DECIMAL_POINT, SOLIDUS, DIGIT_ZERO,
	DIGIT_NINE, SEPARATOR, LATIN_UPPER_A, LATIN_UPPER_E, LATIN_UPPER_F,
	LATIN_UPPER_I, LATIN_UPPER_N, ARRAY_BEGIN, BACKSLASH, ARRAY_END,
	LATIN_A, LATIN_B, LATIN_E, LATIN_F, LATIN_I, LATIN_L, LATIN_N, LATIN_R,
	LATIN_S, LATIN_T, LATIN_U, LATIN_Y, OBJECT_BEGIN, OBJECT_END, ESCAPES,
	REVERSE_ESCAPES, ESCAPED_ARRAY

