# Module: `nupp.data` # Data and text `nupp.data` groups serialization, Unicode, identifiers and byte digests. Reach it directly from the global [`nupp` namespace](stdlib.md); the C and Rust providers remain hidden. ## JSON `encodeJSON` and `decodeJSON` use the mature cjson implementation without exposing its module name: ```nupp local encoded = nupp.data.encodeJSON({name = "Nupp", ready = true}) local decoded = nupp.data.decodeJSON(encoded) assert(decoded.name == "Nupp") ``` `null`, `emptyArray`, `arrayMt`, and `emptyArrayMt` preserve distinctions Lua tables cannot express by themselves. The configuration methods match cjson's established semantics, but live on `nupp.data`. `newJSON()` returns an independent `nupp.data.JSON` encoder/decoder with its own settings: ```nupp local compact = nupp.data.newJSON() compact.encodeKeepBuffer(false) local text = compact.encodeJSON({1, 2, 3}) ``` JSON selects the `cjson` native feature. No `require("cjson")` is needed or recommended. | Member | Result | Purpose | | --- | --- | --- | | `encodeJSON(value)` | `string` | Encode one Lua value. | | `decodeJSON(text)` | `any` | Decode one JSON document. | | `newJSON()` | `nupp.data.JSON` | Create an independently configured codec. | | `null`, `emptyArray` | sentinel values | Represent JSON values that plain Lua tables cannot distinguish. | | `arrayMt`, `emptyArrayMt` | metatables | Mark array-shaped tables explicitly. | Both `nupp.data` and an object returned by `newJSON` provide the configuration methods `encodeEmptyTableAsObject`, `decodeArrayWithArrayMt`, `decodeAllowComment`, `encodeSparseArray`, `encodeMaxDepth`, `decodeMaxDepth`, `encodeNumberPrecision`, `encodeKeepBuffer`, `encodeInvalidNumbers`, `decodeInvalidNumbers`, `encodeEscapeForwardSlash`, `encodeSkipUnsupportedValueTypes`, and `encodeIndent`. Omitting a method's setting reads the current value where the provider supports that form; passing a setting changes only that codec. ## UTF-8 `nupp.data.utf8` treats strings and [`nupp.io.ByteView`](io.md#byte-views) values as byte sequences. Byte offsets are 1-based here so they compose with Lua string positions. Invalid input decodes as U+FFFD while validation remains explicit. ```nupp local utf8 = nupp.data.utf8 assert(utf8.length("A€") == 2) local codepoint, nextByte = utf8.decodeAt("A€", 2) assert(codepoint == 0x20ac and nextByte == 5) codepoint, nextByte = utf8.decodeBefore("A€", nextByte) assert(codepoint == 0x20ac and nextByte == 2) assert(utf8.encode(0x20ac) == "€") assert(utf8.isValid("café")) assert(not utf8.isValid("\xff")) assert(utf8.truncate("A€B", 4) == "A€") ``` `validPrefixLength(value, maxBytes)` returns the largest valid prefix no longer than the byte budget. `truncate` applies that operation to a string. The underlying lua-utf8 provider loads only when this namespace is selected and reached. | Member | Result | Position rule | | --- | --- | --- | | `length(value)` | `integer` | Counts decoded scalar values, replacing malformed bytes individually. | | `decodeAt(value, byteOffset)` | `integer?, integer` | Decodes forward from a 1-based byte offset and returns the next offset. | | `decodeBefore(value, byteOffset)` | `integer?, integer` | Decodes the scalar ending before a 1-based byte offset. | | `encode(codepoint)` | `string` | Encodes one Unicode scalar value. | | `isValid(value)` | `boolean` | Validates the complete byte sequence. | | `validPrefixLength(value, maxBytes)` | `integer` | Finds a valid prefix within a byte budget. | | `truncate(text, maxBytes)` | `string` | Copies that valid prefix. | ## UUIDs `uuid4()` returns a random RFC 9562 version 4 identifier. `uuid7()` returns a time-ordered version 7 identifier, useful when identifier order should roughly follow creation order: ```nupp local objectID = nupp.data.uuid4() local eventID = nupp.data.uuid7() ``` Both are lowercase canonical strings. They share one `uuid` feature and never expose a native UUID object. ## Hashes and checksums Each function accepts a string or immutable [`nupp.io.ByteView`](io.md#byte-views). ```nupp assert(nupp.data.fnv1a64("hello") == "a430d84680aabd0b") assert(nupp.data.sha256("abc") == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad") local checksum = nupp.data.crc32(header) checksum = nupp.data.crc32(body, checksum) ``` `fnv1a64` is a fast non-cryptographic identity rendered as 16 lowercase hexadecimal digits. `sha256` is a cryptographic digest rendered as 64 lowercase hexadecimal digits. `adler32` and `crc32` return unsigned 32-bit numbers and accept a previous result for incremental checksumming. Checksums detect accidental damage; they do not authenticate data. A supplied previous checksum must itself be an unsigned 32-bit integer. FNV-1a, Adler-32 and CRC-32 are pure generated Lua. SHA-256 is independently gated in the shared Rust provider. See [automatic native selection](tooling/build.md#compiler-native-features). | Member | Result | Native provider | | --- | --- | --- | | `uuid4()` | canonical UUID string | shared provider, `uuid` feature | | `uuid7()` | canonical UUID string | shared provider, `uuid` feature | | `fnv1a64(value)` | 16 lowercase hex digits | none | | `sha256(value)` | 64 lowercase hex digits | shared provider, `sha256` feature | | `adler32(value, previous?)` | unsigned 32-bit number | none | | `crc32(value, previous?)` | unsigned 32-bit number | none | JSON, UTF-8, UUIDs, hashes and checksums. ## Submodules | Module | Description | | --- | --- | | `nupp.data.utf8` | UTF-8 codepoint operations over strings and byte views. | ## Constructors ### `newJSON` _constructor_ Creates an independent JSON codec with its own settings. ```nupp local newJSON: function(): JSON ``` #### Returns | Type | Description | | --- | --- | | `JSON` | the new codec | ## Types ### `JSON` _interface_ One independently configured JSON encoder and decoder. ```nupp interface JSON encodeJSON: function(value: any): string decodeJSON: function(text: string): any null: any emptyArray: any arrayMt: metatable<{any}> emptyArrayMt: metatable<{any}> encodeEmptyTableAsObject: function(setting: boolean | string?): boolean decodeArrayWithArrayMt: function(setting: boolean | string?): boolean decodeAllowComment: function(setting: boolean | string?): boolean encodeSparseArray: function(convert: boolean?, ratio: integer?, safe: integer?): (boolean, integer, integer) encodeMaxDepth: function(depth: integer?): integer decodeMaxDepth: function(depth: integer?): integer encodeNumberPrecision: function(precision: integer?): integer encodeKeepBuffer: function(keep: boolean | string?): boolean encodeInvalidNumbers: function(setting: boolean | string?): boolean | string decodeInvalidNumbers: function(setting: boolean | string?): boolean encodeEscapeForwardSlash: function(setting: boolean | string?): boolean encodeSkipUnsupportedValueTypes: function(setting: boolean | string?): boolean encodeIndent: function(indent: string?): string end ``` #### Methods ##### `encodeJSON` Encodes a Lua value as JSON text. ```nupp encodeJSON: function(value: any): string ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `any` | the value to encode | ###### Returns | Type | Description | | --- | --- | | `string` | the encoded JSON document | ##### `decodeJSON` Decodes one JSON document into Lua values. ```nupp decodeJSON: function(text: string): any ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `text` | `string` | the JSON document to decode | ###### Returns | Type | Description | | --- | --- | | `any` | the decoded value | ##### `encodeEmptyTableAsObject` Sets whether an empty table encodes as an object, or reads the current setting when omitted. ```nupp encodeEmptyTableAsObject: function(setting: boolean | string?): boolean ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | true or "on" for `{}`, false or "off" for `[]` | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether empty tables encode as objects | ##### `decodeArrayWithArrayMt` Sets whether decoded arrays carry `arrayMt`, or reads the current setting when omitted. ```nupp decodeArrayWithArrayMt: function(setting: boolean | string?): boolean ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether decoded arrays carry `arrayMt` | ##### `decodeAllowComment` Sets whether the decoder accepts comments, or reads the current setting when omitted. ```nupp decodeAllowComment: function(setting: boolean | string?): boolean ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether comments are accepted | ##### `encodeSparseArray` Configures how excessively sparse arrays are encoded, or reads the current settings when every argument is omitted. ```nupp encodeSparseArray: function(convert: boolean?, ratio: integer?, safe: integer?): (boolean, integer, integer) ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `convert` | `boolean?` | whether sparse arrays become JSON objects instead of raising | | `ratio` | `integer?` | the maximum ratio between the highest index and item count | | `safe` | `integer?` | the array size below which sparsity is always accepted | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether sparse arrays are converted | | `integer` | the current ratio limit | | `integer` | the current safe size | ##### `encodeMaxDepth` Sets the maximum nested-container depth accepted by the encoder, or reads the current limit when omitted. ```nupp encodeMaxDepth: function(depth: integer?): integer ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `depth` | `integer?` | the new maximum depth | ###### Returns | Type | Description | | --- | --- | | `integer` | the current maximum depth | ##### `decodeMaxDepth` Sets the maximum nested-container depth accepted by the decoder, or reads the current limit when omitted. ```nupp decodeMaxDepth: function(depth: integer?): integer ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `depth` | `integer?` | the new maximum depth | ###### Returns | Type | Description | | --- | --- | | `integer` | the current maximum depth | ##### `encodeNumberPrecision` Sets the significant-digit precision used to encode numbers, or reads the current precision when omitted. ```nupp encodeNumberPrecision: function(precision: integer?): integer ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `precision` | `integer?` | the new number of significant digits | ###### Returns | Type | Description | | --- | --- | | `integer` | the current precision | ##### `encodeKeepBuffer` Sets whether the encoder reuses its internal buffer, or reads the current setting when omitted. ```nupp encodeKeepBuffer: function(keep: boolean | string?): boolean ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `keep` | `boolean | string?` | the new setting | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether the internal buffer is retained | ##### `encodeInvalidNumbers` Configures encoding of NaN and infinities, or reads the current setting when omitted. ```nupp encodeInvalidNumbers: function(setting: boolean | string?): boolean | string ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | false to reject them, true to emit them, or "null" to emit null | ###### Returns | Type | Description | | --- | --- | | `boolean | string` | the active invalid-number setting | ##### `decodeInvalidNumbers` Sets whether the decoder accepts NaN and infinities, or reads the current setting when omitted. ```nupp decodeInvalidNumbers: function(setting: boolean | string?): boolean ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether invalid numbers are accepted | ##### `encodeEscapeForwardSlash` Sets whether `/` is escaped in JSON strings, or reads the current setting when omitted. ```nupp encodeEscapeForwardSlash: function(setting: boolean | string?): boolean ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether forward slashes are escaped | ##### `encodeSkipUnsupportedValueTypes` Sets whether unsupported values are skipped instead of raising, or reads the current setting when omitted. ```nupp encodeSkipUnsupportedValueTypes: function(setting: boolean | string?): boolean ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether unsupported values are skipped | ##### `encodeIndent` Sets the indentation used for encoded containers, or reads the current indentation when omitted. ```nupp encodeIndent: function(indent: string?): string ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `indent` | `string?` | the indentation string | ###### Returns | Type | Description | | --- | --- | | `string` | the current indentation string | #### Fields | Name | Type | Description | | --- | --- | --- | | `null` | `any` | Sentinel that decodes from and encodes as JSON null. | | `emptyArray` | `any` | Sentinel that always encodes as an empty JSON array. | | `arrayMt` | `metatable\<{any}\>` | Metatable marking a table to encode as a JSON array. | | `emptyArrayMt` | `metatable\<{any}\>` | Metatable marking a table to encode as an empty JSON array. | ### `JSONEncodable` _interface_ Values that can encode themselves as JSON text. ```nupp interface JSONEncodable toJSON: function(self): string end ``` #### Methods ##### `toJSON` ```nupp toJSON: function(self): string ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `?` | `self` | | ###### Returns | Type | Description | | --- | --- | | `string` | | ## Functions ### `adler32` _function_ Computes or continues an Adler-32 checksum. ```nupp local adler32: function(value: string | nupp.io.ByteView, previous: integer?): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `string | nupp.io.ByteView` | the bytes to checksum | | `previous` | `integer?` | a previous Adler-32 value, or 1 to start | #### Returns | Type | Description | | --- | --- | | `integer` | the unsigned 32-bit checksum | ### `crc32` _function_ Computes or continues a CRC-32 checksum. ```nupp local crc32: function(value: string | nupp.io.ByteView, previous: integer?): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `string | nupp.io.ByteView` | the bytes to checksum | | `previous` | `integer?` | a previous CRC-32 value, or 0 to start | #### Returns | Type | Description | | --- | --- | | `integer` | the unsigned 32-bit checksum | ### `decodeAllowComment` _function_ Sets whether the decoder accepts comments, or reads the current setting when omitted. ```nupp local decodeAllowComment: function(setting: boolean | string?): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | #### Returns | Type | Description | | --- | --- | | `boolean` | whether comments are accepted | ### `decodeArrayWithArrayMt` _function_ Sets whether decoded arrays carry `arrayMt`, or reads the current setting when omitted. ```nupp local decodeArrayWithArrayMt: function(setting: boolean | string?): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | #### Returns | Type | Description | | --- | --- | | `boolean` | whether decoded arrays carry `arrayMt` | ### `decodeInvalidNumbers` _function_ Sets whether the decoder accepts NaN and infinities, or reads the current setting when omitted. ```nupp local decodeInvalidNumbers: function(setting: boolean | string?): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | #### Returns | Type | Description | | --- | --- | | `boolean` | whether invalid numbers are accepted | ### `decodeJSON` _function_ Decodes one JSON document into Lua values. ```nupp local decodeJSON: function(text: string): any ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `text` | `string` | the JSON document to decode | #### Returns | Type | Description | | --- | --- | | `any` | the decoded value | ### `decodeMaxDepth` _function_ Sets the maximum nested-container depth accepted by the decoder, or reads the current limit when omitted. ```nupp local decodeMaxDepth: function(depth: integer?): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `depth` | `integer?` | the new maximum depth | #### Returns | Type | Description | | --- | --- | | `integer` | the current maximum depth | ### `encodeEmptyTableAsObject` _function_ Sets whether an empty table encodes as an object, or reads the current setting when omitted. ```nupp local encodeEmptyTableAsObject: function(setting: boolean | string?): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | true or "on" for `{}`, false or "off" for `[]` | #### Returns | Type | Description | | --- | --- | | `boolean` | whether empty tables encode as objects | ### `encodeEscapeForwardSlash` _function_ Sets whether `/` is escaped in JSON strings, or reads the current setting when omitted. ```nupp local encodeEscapeForwardSlash: function(setting: boolean | string?): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | #### Returns | Type | Description | | --- | --- | | `boolean` | whether forward slashes are escaped | ### `encodeIndent` _function_ Sets the indentation used for encoded containers, or reads the current indentation when omitted. ```nupp local encodeIndent: function(indent: string?): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `indent` | `string?` | the indentation string | #### Returns | Type | Description | | --- | --- | | `string` | the current indentation string | ### `encodeInvalidNumbers` _function_ Configures encoding of NaN and infinities, or reads the current setting when omitted. ```nupp local encodeInvalidNumbers: function(setting: boolean | string?): boolean | string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | false to reject them, true to emit them, or "null" to emit null | #### Returns | Type | Description | | --- | --- | | `boolean | string` | the active invalid-number setting | ### `encodeJSON` _function_ Encodes a Lua value as JSON text. ```nupp local encodeJSON: function(value: any): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `any` | the value to encode | #### Returns | Type | Description | | --- | --- | | `string` | the encoded JSON document | ### `encodeKeepBuffer` _function_ Sets whether the encoder reuses its internal buffer, or reads the current setting when omitted. ```nupp local encodeKeepBuffer: function(keep: boolean | string?): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `keep` | `boolean | string?` | the new setting | #### Returns | Type | Description | | --- | --- | | `boolean` | whether the internal buffer is retained | ### `encodeMaxDepth` _function_ Sets the maximum nested-container depth accepted by the encoder, or reads the current limit when omitted. ```nupp local encodeMaxDepth: function(depth: integer?): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `depth` | `integer?` | the new maximum depth | #### Returns | Type | Description | | --- | --- | | `integer` | the current maximum depth | ### `encodeNumberPrecision` _function_ Sets the significant-digit precision used to encode numbers, or reads the current precision when omitted. ```nupp local encodeNumberPrecision: function(precision: integer?): integer ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `precision` | `integer?` | the new number of significant digits | #### Returns | Type | Description | | --- | --- | | `integer` | the current precision | ### `encodeSkipUnsupportedValueTypes` _function_ Sets whether unsupported values are skipped instead of raising, or reads the current setting when omitted. ```nupp local encodeSkipUnsupportedValueTypes: function(setting: boolean | string?): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `setting` | `boolean | string?` | the new setting | #### Returns | Type | Description | | --- | --- | | `boolean` | whether unsupported values are skipped | ### `encodeSparseArray` _function_ Configures how excessively sparse arrays are encoded, or reads the current settings when every argument is omitted. ```nupp local encodeSparseArray: function(convert: boolean?, ratio: integer?, safe: integer?): (boolean, integer, integer) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `convert` | `boolean?` | whether sparse arrays become JSON objects instead of raising | | `ratio` | `integer?` | the maximum ratio between the highest index and item count | | `safe` | `integer?` | the array size below which sparsity is always accepted | #### Returns | Type | Description | | --- | --- | | `boolean` | whether sparse arrays are converted | | `integer` | the current ratio limit | | `integer` | the current safe size | ### `fnv1a64` _function_ Computes the 64-bit FNV-1a digest of bytes. ```nupp local fnv1a64: function(value: string | nupp.io.ByteView): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `string | nupp.io.ByteView` | the bytes to hash | #### Returns | Type | Description | | --- | --- | | `string` | the lowercase hexadecimal digest | ### `sha256` _function_ Computes the SHA-256 digest of bytes. ```nupp local sha256: function(value: string | nupp.io.ByteView): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `value` | `string | nupp.io.ByteView` | the bytes to hash | #### Returns | Type | Description | | --- | --- | | `string` | the lowercase hexadecimal digest | ### `uuid4` _function_ Generates a random version 4 UUID. ```nupp local uuid4: function(): string ``` #### Returns | Type | Description | | --- | --- | | `string` | the canonical lowercase UUID text | ### `uuid7` _function_ Generates a time-ordered version 7 UUID. ```nupp local uuid7: function(): string ``` #### Returns | Type | Description | | --- | --- | | `string` | the canonical lowercase UUID text | ## Values ### `arrayMt` _variable_ Metatable marking a table to encode as a JSON array. ```nupp local arrayMt: metatable<{any}> ``` ### `emptyArray` _variable_ Sentinel that always encodes as an empty JSON array. ```nupp local emptyArray: any ``` ### `emptyArrayMt` _variable_ Metatable marking a table to encode as an empty JSON array. ```nupp local emptyArrayMt: metatable<{any}> ``` ### `null` _variable_ Sentinel that decodes from and encodes as JSON null. ```nupp local null: any ```