2019-06-24 14:36:18 +00:00
|
|
|
nim-serialization
|
|
|
|
=================
|
|
|
|
|
|
|
|
[![Build Status](https://travis-ci.org/status-im/nim-serialization.svg?branch=master)](https://travis-ci.org/status-im/nim-serialization)
|
2019-08-24 03:22:46 +00:00
|
|
|
[![Build status](https://ci.appveyor.com/api/projects/status/muejuk735c11brjd/branch/master?svg=true)](https://ci.appveyor.com/project/nimbus/nim-serialization/branch/master)
|
2019-06-24 14:36:18 +00:00
|
|
|
[![License: Apache](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
|
|
|
|
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
|
|
|
|
|
|
|
|
|
|
|
## Introduction
|
|
|
|
|
|
|
|
The `serialization` package aims to provide a common generic and efficient
|
|
|
|
interface for marshaling Nim values to and from various serialized formats.
|
|
|
|
Individual formats are implemented in separated packages such as
|
|
|
|
[`json_serialization`](https://github.com/status-im/nim-json-serialization)
|
|
|
|
while this package provides the common interfaces shared between all of them
|
|
|
|
and the means to customize your Nim types for the purposes of serialization.
|
|
|
|
|
|
|
|
The internal mechanisms of the library allow for implementing the required
|
|
|
|
marshaling logic in highly efficient way that goes from bytes to Nim values
|
|
|
|
and vice versa without allocating any intermediate structures.
|
|
|
|
|
|
|
|
## Defining serialization formats
|
|
|
|
|
|
|
|
A serialization format is implemented through defining a `Reader` and `Writer`
|
|
|
|
type for the format and then by providing the following type declaration:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
serializationFormat Json, # This is the name of the format.
|
|
|
|
# Most APIs provided by the library will accept
|
|
|
|
# this identifier as a required parameter.
|
|
|
|
|
|
|
|
Reader = JsonReader, # The associated Reader type.
|
|
|
|
Writer = JsonWriter, # The associated Writer type.
|
|
|
|
|
|
|
|
PreferedOutput = string, # APIs such as `Json.encode` will return this type.
|
|
|
|
# The type must support the following operations:
|
|
|
|
# proc initWithCapacity(_: type T, n: int)
|
|
|
|
# proc add(v: var T, bytes: openarray[byte])
|
|
|
|
# By default, the PreferedOutput is `seq[byte]`.
|
|
|
|
|
|
|
|
mimeType = "application/json", # Mime type associated with the format (Optional).
|
|
|
|
fileExt = "json" # File extension associated with the format (Optional).
|
|
|
|
```
|
|
|
|
|
|
|
|
## Common API
|
|
|
|
|
|
|
|
Most of the time, you'll be using the following high-level APIs when encoding
|
|
|
|
and decoding values:
|
|
|
|
|
|
|
|
#### `Format.encode(value: auto, params: varargs): Format.PreferedOutput`
|
|
|
|
|
|
|
|
Encodes a value in the specified format returning the preferred output type
|
|
|
|
for the format (usually `string` or `seq[byte]`). All extra params will be
|
|
|
|
forwarded without modification to the constructor of the used `Writer` type.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
assert Json.encode(@[1, 2, 3], pretty = false) == "[1, 2, 3]"
|
|
|
|
```
|
|
|
|
|
|
|
|
#### `Format.decode(input: openarray[byte]|string, RecordType: type, params: varargs): RecordType`
|
|
|
|
|
|
|
|
Decodes and returns a value of the specified `RecordType`. All params will
|
|
|
|
be forwarded without modification to the used `Reader` type. A Format-specific
|
|
|
|
descendant of `SerializationError` may be thrown in case of error.
|
|
|
|
|
|
|
|
#### `Format.saveFile(filename: string, params: varargs)`
|
|
|
|
|
|
|
|
Similar to `encode`, but saves the result in a file.
|
|
|
|
|
|
|
|
#### `Format.loadFile`
|
|
|
|
|
|
|
|
Similar to `decode`, but treats the contents of a file as an input.
|
|
|
|
|
|
|
|
#### `reader.readValue(RecordType: type): RecordType`
|
|
|
|
|
|
|
|
Reads a single value of the designated type from the stream associated with a
|
|
|
|
particular reader.
|
|
|
|
|
|
|
|
#### `writer.writeValue(value: auto)`
|
|
|
|
|
|
|
|
Encodes a single value and writes it to the output stream of a paticular writer.
|
|
|
|
|
|
|
|
### Custom serialization of user-defined types
|
|
|
|
|
|
|
|
By default, record types will have all of their fields serialized. You can
|
|
|
|
alter this behavior by attaching the `dontSerialize(varargs[Format])` pragma
|
|
|
|
to black-list fields or the `serialize(varargs[Format])` to white-list fields.
|
|
|
|
If no formats are listed in the pragmas above, they will affect all formats.
|
|
|
|
The pragma `serializedFieldName(name: string)` can be used to modify the name
|
|
|
|
of the field in formats such as Json and XML.
|
|
|
|
|
|
|
|
Alternatively, if you are not able to modify the definition of a particular
|
|
|
|
Nim type, you can use the `serializedFields` macro to achive the same in less
|
|
|
|
instrusive way.
|
|
|
|
|
|
|
|
The following two definitions can be consired equivalent:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
type
|
|
|
|
Foo = object
|
|
|
|
a: string
|
|
|
|
b {.dontSerialize.}: int
|
|
|
|
c {.dontSerialize(JSON).}: float
|
|
|
|
d {.serializedFieldName("z").}: int
|
|
|
|
|
|
|
|
serializedFields Foo:
|
|
|
|
a
|
|
|
|
c [-JSON]
|
|
|
|
# The `d` field is renamed to `z`:
|
|
|
|
d -> z
|
|
|
|
```
|
|
|
|
|
|
|
|
As you can see, `serializedFields` accepts a block where each serialzied
|
|
|
|
field is listed on a separate line. The `->` operator is used to indicate
|
|
|
|
field renames, while the optional `[]` modifiers can be used to while-list
|
|
|
|
or black-list specific formats where the field should appear (using `+`
|
|
|
|
and `-` respectively).
|
|
|
|
|
|
|
|
#### `customSerialization(RecordType: type, spec)`
|
|
|
|
#### `Format.customSerialization(RecordType, spec)`
|
|
|
|
#### `customSerialization(RecordType.field, spec)`
|
|
|
|
#### `Format.customSerialization(Record.field, spec)`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### `Record.totalSerializedFields(Format)`
|
|
|
|
|
|
|
|
Returns the number of serialized fields in the specified format.
|
|
|
|
|
|
|
|
### Implementing Readers
|
|
|
|
|
|
|
|
### Implementing Writers
|
|
|
|
|
|
|
|
## Contributing
|
|
|
|
|
|
|
|
When submitting pull requests, please add test cases for any new features
|
|
|
|
or fixes and make sure `nimble test` is still able to execute the entire
|
|
|
|
test suite successfully.
|
|
|
|
|
|
|
|
[BOUNTIES]: https://github.com/status-im/nim-confutils/issues?q=is%3Aissue+is%3Aopen+label%3Abounty
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
Licensed and distributed under either of
|
|
|
|
|
|
|
|
* MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT
|
|
|
|
|
|
|
|
or
|
|
|
|
|
|
|
|
* Apache License, Version 2.0, ([LICENSE-APACHEv2](LICENSE-APACHEv2) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
|
2019-07-13 15:05:06 +00:00
|
|
|
at your option. These files may not be copied, modified, or distributed except according to those terms.
|
2019-06-24 14:36:18 +00:00
|
|
|
|