You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.8 KiB
147 lines
3.8 KiB
'use strict'
|
|
|
|
// eslint-disable-next-line
|
|
const STR_ESCAPE = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]|[\ud800-\udbff](?![\udc00-\udfff])|(?:[^\ud800-\udbff]|^)[\udc00-\udfff]/
|
|
|
|
module.exports = class Serializer {
|
|
constructor (options = {}) {
|
|
switch (options.rounding) {
|
|
case 'floor':
|
|
this.parseInteger = Math.floor
|
|
break
|
|
case 'ceil':
|
|
this.parseInteger = Math.ceil
|
|
break
|
|
case 'round':
|
|
this.parseInteger = Math.round
|
|
break
|
|
default:
|
|
this.parseInteger = Math.trunc
|
|
break
|
|
}
|
|
}
|
|
|
|
asInteger (i) {
|
|
if (typeof i === 'bigint') {
|
|
return i.toString()
|
|
} else if (Number.isInteger(i)) {
|
|
return '' + i
|
|
} else {
|
|
/* eslint no-undef: "off" */
|
|
const integer = this.parseInteger(i)
|
|
if (Number.isNaN(integer) || !Number.isFinite(integer)) {
|
|
throw new Error(`The value "${i}" cannot be converted to an integer.`)
|
|
} else {
|
|
return '' + integer
|
|
}
|
|
}
|
|
}
|
|
|
|
asNumber (i) {
|
|
const num = Number(i)
|
|
if (Number.isNaN(num)) {
|
|
throw new Error(`The value "${i}" cannot be converted to a number.`)
|
|
} else if (!Number.isFinite(num)) {
|
|
return null
|
|
} else {
|
|
return '' + num
|
|
}
|
|
}
|
|
|
|
asBoolean (bool) {
|
|
return bool && 'true' || 'false' // eslint-disable-line
|
|
}
|
|
|
|
asDateTime (date) {
|
|
if (date === null) return '""'
|
|
if (date instanceof Date) {
|
|
return '"' + date.toISOString() + '"'
|
|
}
|
|
if (typeof date === 'string') {
|
|
return '"' + date + '"'
|
|
}
|
|
throw new Error(`The value "${date}" cannot be converted to a date-time.`)
|
|
}
|
|
|
|
asDate (date) {
|
|
if (date === null) return '""'
|
|
if (date instanceof Date) {
|
|
return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 10) + '"'
|
|
}
|
|
if (typeof date === 'string') {
|
|
return '"' + date + '"'
|
|
}
|
|
throw new Error(`The value "${date}" cannot be converted to a date.`)
|
|
}
|
|
|
|
asTime (date) {
|
|
if (date === null) return '""'
|
|
if (date instanceof Date) {
|
|
return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(11, 19) + '"'
|
|
}
|
|
if (typeof date === 'string') {
|
|
return '"' + date + '"'
|
|
}
|
|
throw new Error(`The value "${date}" cannot be converted to a time.`)
|
|
}
|
|
|
|
asString (str) {
|
|
const quotes = '"'
|
|
if (str instanceof Date) {
|
|
return quotes + str.toISOString() + quotes
|
|
} else if (str === null) {
|
|
return quotes + quotes
|
|
} else if (str instanceof RegExp) {
|
|
str = str.source
|
|
} else if (typeof str !== 'string') {
|
|
str = str.toString()
|
|
}
|
|
|
|
// Fast escape chars check
|
|
if (!STR_ESCAPE.test(str)) {
|
|
return quotes + str + quotes
|
|
}
|
|
|
|
if (str.length < 42) {
|
|
return this.asStringSmall(str)
|
|
} else {
|
|
return JSON.stringify(str)
|
|
}
|
|
}
|
|
|
|
// magically escape strings for json
|
|
// relying on their charCodeAt
|
|
// everything below 32 needs JSON.stringify()
|
|
// every string that contain surrogate needs JSON.stringify()
|
|
// 34 and 92 happens all the time, so we
|
|
// have a fast case for them
|
|
asStringSmall (str) {
|
|
const l = str.length
|
|
let result = ''
|
|
let last = 0
|
|
let found = false
|
|
let surrogateFound = false
|
|
let point = 255
|
|
// eslint-disable-next-line
|
|
for (var i = 0; i < l && point >= 32; i++) {
|
|
point = str.charCodeAt(i)
|
|
if (point >= 0xD800 && point <= 0xDFFF) {
|
|
// The current character is a surrogate.
|
|
surrogateFound = true
|
|
}
|
|
if (point === 34 || point === 92) {
|
|
result += str.slice(last, i) + '\\'
|
|
last = i
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
result = str
|
|
} else {
|
|
result += str.slice(last)
|
|
}
|
|
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
|
|
}
|
|
}
|