schemer

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2021 License: MIT Imports: 13 Imported by: 0

README

schemer

Lightweight and robust data encoding library for Go

Schemer provides an API to construct schemata that describe data structures; a schema is then used to encode and decode values into sequences of bytes to be sent over the network or written to a file.

Schemer seeks to be an alternative to protobuf or Avro, but it can also be used as a substitute for JSON.

Features

  • Compact binary data format
  • High-speed encoding and decoding
  • Forward and backward compatibility
  • No code generation and no new language to learn
  • Simple and lightweight library with no external dependencies
  • Supports custom encoding for user-defined data types
  • JavaScript library for web browser interoperability (coming soon!)

Why?

Schemer is an attempt to further simplify data encoding. Unlike other encoding libraries that use interface description languages (i.e. protobuf), schemer allows developers to construct schemata programmatically with an API. Rather than generating code from a schema, a schema can be constructed from code. In Go, schemata can be generated from Go types using the reflection library. This subtlety adds a surprising amount of flexibility and extensibility to the encoding library.

Here's how schemer stacks up against other encoding formats:

Property JSON XML MessagePack Protobuf Thrift Avro Gob Schemer
Human-Readable 😐
Support for Many Programming Languages
Widely Adopted
Precise Encoding of Numbers 😐
Binary Strings
Compact Encoded Payload ❌❌ ❌❌
Fast Encoding / Decoding 😐 😐
Backward Compatibility 😐 😐 😐
Forward Compatibility 😐 😐 😐
No Language To Learn 😐
Schema Support 😐 😐
Supports Fixed-field Objects
Works on Web Browser 😐 📆 soon…

Types

schemer uses type information provided by the schema to encode values. The following are all of the types that are supported:

  • Integer
    • Can be signed or unsigned
    • Fixed-size or variable-size [^1]
      • Fixed-size integers can be 8, 16, 32, 64, or 128 bits
  • Floating-point number (32 or 64-bit)
  • Complex number (64 or 128-bit)
  • Boolean
  • Enumeration
  • String
    • Can support any encoding, including UTF-8 and binary
    • Fixed-size or variable-size [^2]
  • Array
    • Fixed-size or variable-size
  • Object w/fixed fields (i.e. struct)
  • Object w/variable fields (i.e. map)
  • Schema (i.e. a schemer schema)
  • Dynamically-typed value (i.e. variant)
  • User-defined types
    • A few common types are provided for representing timestamps, time durations, IP addresses, UUIDs, regular expressions, etc.

[^1]: By default, integer types are encoded as variable integers, as this format will most likely generate the smallest encoded values. [^2]: By default, string types are encoded as variable-size strings. Fixed-size strings are padded with trailing null bytes / zeros.

Schema JSON Specification

Types
Type JSON Type Name Additional Options
Fixed-size Integer int * signed - boolean indicating if integer is signed or unsigned
* bits - one of the following numbers indicating the size of the integer: 8, 16, 32, 64, 128, 256, 512, 1024
Variable-size Integer int * signed - boolean indicating if integer is signed or unsigned
* bits - must be null or omitted
Floating-point Number float * bits - one of the following numbers indicating the size of the floating-point: 32, 64
Complex Number complex * bits - one of the following numbers indicating the size of the complex number: 64, 128
Boolean bool
Enum enum * values - an object mapping strings to integer values
Fixed-Length String string * length - the length of the string in bytes
Variable-Length String string * length - must be null or omitted
Fixed-Length Array array * length - the length of the string in bytes
Variable-Length Array array * length - must be null or omitted
Object w/fixed fields object * fields - an array of fields. Each field is an type object with keys:
name[^3], type, and any additional options for the type
Object w/variable fields object * fields - must be null or omitted
Variant variant

[^3]: It is strongly encouraged to use camelCase for object field names.

Example

Here's a struct with three fields:

  • firstName (string)
  • lastName (string)
  • age (uint8 - unsigned integer requiring a single byte)
{
  "type": "object",
  "fields": [
    {
      "name": "firstName",
      "type": "string"
    }, {
      "name": "lastName",
      "type": "string"
    }, {
      "name": "age",
      "type": "int",
      "signed": false,
      "size": 1
    }
  ]
}

Type Compatibility

When decoding values from one type to another, schemer employs the following compatibility rules. These rules, while rather opinionated, provide safe defaults when decoding values. Users who want to carefully craft how values are decoded from one type to another can simply create a custom type.

As a general rule, types are only compatible with themselves (i.e. boolean values can only be decoded to boolean values). The table below outlines a few notable exceptions and describes how using "weak" decoding mode can increase type compatibility by sacrificing type safety and by making a few assumptions.

Destination
Source int float complex bool enum string array (see #12) object
int ✔ #1 ✔ #1 ✔ #1 ❕ #6 ❕ #7 ❕ #9
float ✔ #1 ✔ #1 ✔ #1 ❕ #9
complex ✔ #1 ✔ #1 ✔ #1 ❕ #9 ❕ #11
bool ❕ #6 ❕ #10
enum ❕ #7 ✔ #2 ✔ #2
string ❕ #8 ❕ #8 ❕ #8 ❕ #10 ✔ #2
array (see #12) ❕ #11 ✔ #3
object ✔ #4

Legend:
✔ - indicates compatibility according to the specified rule
❕- indicates compatibility according to the specified rule only if weak decoding is used
❌ - indicates that the source type cannot be decoded to the destination

Compatibility Rules:
  1. Any number can be decoded to any other number, provided the decoded value can be stored into the destination without losing any precision. If weak decoding is specified, we loosen this restriction slightly by allowing floating-point and complex number conversions to lose precision.

    For example, if the number 3.14 is decoded, it can be stored as a float or complex number, but it cannot be stored as an integer. Similarly, the number 500 can be stored into a uint16 but not a uint8, since uint8 can only store values between 0 and 255.

  2. Enumerations are decoded to other enumerations by performing a case-insensitive match on the named value, not a match on the numeric value. If multiple matches occur, a case-sensitive match is then performed. Decoding fails if the decoded named value does not match a named value in the destination enumeration. Enumerations can also be converted to strings and vice-versa by matching on the enumeration's named value.

  3. Arrays can be decoded to arrays if the element type and array length is compatible. Specifically, when the destination array is of fixed-size and does not support null values, the decoded array must match exactly in length.

  4. Objects are decoded to other objects by performing a case-insensitive match on the key or field name. If multiple matches occur, a case-sensitive match is then performed. When the destination is an object with fixed fields and the decoded value does not have a matching key or field name, the key / field is simply skipped and will remain unchanged.

  5. Null values can only be decoded to destinations that support null values (i.e. pointers), but a non-null value can be decoded even if the destination does not support null values.

The following compatibility rules apply for weak decoding only:

  1. The boolean value true can be converted to the integer value 1, and the boolean value false can be converted to the integer value 0. Similarly, the integer 0 will be decoded as false, and all other integers are decoded as true.
  2. Enumerations can be converted to integer values and vice-versa, and they are matched on the enumeration's numeric value.
  3. Strings can be decoded to numeric values by considering the string format according to the table below. The resulting numeric value is compatible with the destination according to the relevant compatibility rules.
  4. Numbers are always encoded to strings in base 10.
  5. Boolean values true and false are converted to string values "true" and "false" respectively. Strings "1", "t", "T", "TRUE", "true", and "True" can be converted to the boolean value true. Strings "0", "f", "F", "FALSE", "false", and "False" can be converted to boolean value false.
  6. Complex numbers may be converted into 2-element arrays of floating-point numbers and vice-versa. The real part of the complex number will be matched with array element 0, and the complex part will be matched with array element 1.
  7. Single-element arrays can be decoded to a destination that is compatible with the array element and vice-versa.
String to number decoding:
String Example Regular Expression Decoded As
"-3.14" Number, base 10
"0b1101" Number, base 2
"0775" Number, base 8
"0x2020" Number, base 16
"2.34 + 2i" Complex number, base 10

Credits

This library was created on April 14, 2021, the day of Bernie Madoff's death. What a schemer! May he rest in peace.

Special thanks to Benjamin Pritchard for his significant contributions to this library and for making it a reality.

Documentation

Index

Constants

View Source
const (
	NullMask     = 0x80 // nullable bit
	CustomMask   = 0x40 // custom schema bit
	CustomIDMask = 0x3F // custom schema identifier

	// FixedInt is 0b000 nnns where s is the signed/unsigned bit and
	// n represents the encoded integer size in (8 << n) bits.
	FixedIntMask     = 0x70
	FixedIntByte     = 0x00
	FixedIntBitsMask = 0x0E // Note: Needs to be shifted right 1
	IntSignedMask    = 0x01

	VarIntMask = 0x7E // 0b001 000s where s is the signed/unsigned bit
	VarIntByte = 0x10

	// Float is 0b001 01nn where n is the floating-point size in (32 << n) bits
	FloatMask     = 0x7C
	FloatBitsMask = 0x03
	FloatByte     = 0x14

	// Complex is 0b001 10nn where n is the complex number size in (64 << n) bits
	ComplexMask     = 0x7C
	ComplexBitsMask = 0x03
	ComplexByte     = 0x18

	BoolMask = 0x7F // 0b001 1100
	BoolByte = 0x1C

	EnumMask = 0x7F // 0b001 1101
	EnumByte = 0x1D

	StringMask      = 0x7F // 0b010 000f where f indicates fixed-length string
	VarStringByte   = 0x20
	FixedStringByte = 0x21

	ArrayMask      = 0x7F // 0b010 010f where f indicates fixed-length array
	VarArrayByte   = 0x24
	FixedArrayByte = 0x25

	// Object is 0b010 100f where f indicates that the object has fixed fields
	ObjectMask      = 0x7F
	VarObjectByte   = 0x28
	FixedObjectByte = 0x29
)

Collection of bit masks and values for the type byte of an encoded schema

View Source
const StructTagName string = "schemer"

StructTagName is the Go struct tag name used by schemer

Variables

This section is empty.

Functions

func PreDecode

func PreDecode(r io.Reader, v *reflect.Value, nullable bool) (bool, error)

PreDecode is a helper function that should be called by each Schema's Decode routine. It removes exactly one level of indirection for v and reads the null byte if nullable is set. If a null value is read, (true, nil) is returned, indicating that no further processing is needed by the decoder who called this routine. This routine also ensures that the destination value is settable and returns errors if not. Finally, this routine populates nested pointer values recursively, as needed.

func PreEncode

func PreEncode(w io.Writer, v *reflect.Value, nullable bool) (bool, error)

PreEncode is a helper function that should be called by each Schema's Encode routine. It dereferences v if the value is a pointer or interface type and writes the null byte if nullable is set. If nullable is false and v resolves to nil, an error is returned. If nullable is true and v resolves to nil, (true, nil) is returned, indicating that no further processing is needed by the encoder who called this routine. Otherwise, false, nil is returned.

func ReadUvarint

func ReadUvarint(r io.Reader) (uint64, error)

ReadUvarint reads an Uvarint from r one byte at a time

func Register

func Register(ifaces ...interface{}) error

Register records custom schema generators that implement `SchemaOfType`, `DecodeSchema`, and/or `DecodeSchemaJSON`. When `schemer.SchemaOfType` is called, `SchemaOfType` is called on each registered schema generator to determine if a custom Schema should be used for a given type.

func WriteUvarint

func WriteUvarint(w io.Writer, v uint64) error

WriteUvarint writes v to w as an Uvarint

Types

type BoolSchema

type BoolSchema struct {
	SchemaOptions
}

BoolSchema is a Schema for encoding and decoding boolean values

func (*BoolSchema) Decode

func (s *BoolSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and stores it in i

func (*BoolSchema) DecodeValue

func (s *BoolSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and stores it in v

func (*BoolSchema) Encode

func (s *BoolSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*BoolSchema) EncodeValue

func (s *BoolSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*BoolSchema) GoType

func (s *BoolSchema) GoType() reflect.Type

GoType returns the default Go type that represents the schema

func (*BoolSchema) MarshalJSON

func (s *BoolSchema) MarshalJSON() ([]byte, error)

MarshalJSON encodes the schema in a JSON format

func (*BoolSchema) MarshalSchemer

func (s *BoolSchema) MarshalSchemer() ([]byte, error)

MarshalSchemer encodes the schema in a portable binary format

type ComplexSchema

type ComplexSchema struct {
	SchemaOptions

	Bits int // must be 64 or 128
}

func (*ComplexSchema) Decode

func (s *ComplexSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*ComplexSchema) DecodeValue

func (s *ComplexSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*ComplexSchema) Encode

func (s *ComplexSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*ComplexSchema) EncodeValue

func (s *ComplexSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*ComplexSchema) GoType

func (s *ComplexSchema) GoType() reflect.Type

func (*ComplexSchema) MarshalJSON

func (s *ComplexSchema) MarshalJSON() ([]byte, error)

func (*ComplexSchema) MarshalSchemer

func (s *ComplexSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

func (*ComplexSchema) Valid

func (s *ComplexSchema) Valid() bool

type DateSchema

type DateSchema struct {
	SchemaOptions
}

func (*DateSchema) Decode

func (s *DateSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*DateSchema) DecodeValue

func (s *DateSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded valuethe input stream and store it in v

func (*DateSchema) Encode

func (s *DateSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*DateSchema) EncodeValue

func (s *DateSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of he output stream

func (*DateSchema) GoType

func (s *DateSchema) GoType() reflect.Type

func (*DateSchema) MarshalJSON

func (s *DateSchema) MarshalJSON() ([]byte, error)

func (*DateSchema) MarshalSchemer

func (s *DateSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

type EnumSchema

type EnumSchema struct {
	SchemaOptions

	Values map[int]string
}

func (*EnumSchema) Decode

func (s *EnumSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*EnumSchema) DecodeValue

func (s *EnumSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*EnumSchema) Encode

func (s *EnumSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*EnumSchema) EncodeValue

func (s *EnumSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output streamtream

func (*EnumSchema) GoType

func (s *EnumSchema) GoType() reflect.Type

func (*EnumSchema) MarshalJSON

func (s *EnumSchema) MarshalJSON() ([]byte, error)

func (EnumSchema) MarshalSchemer

func (s EnumSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

type FixedArraySchema

type FixedArraySchema struct {
	SchemaOptions

	Length  int
	Element Schema
}

func (*FixedArraySchema) Decode

func (s *FixedArraySchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*FixedArraySchema) DecodeValue

func (s *FixedArraySchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*FixedArraySchema) Encode

func (s *FixedArraySchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*FixedArraySchema) EncodeValue

func (s *FixedArraySchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*FixedArraySchema) GoType

func (s *FixedArraySchema) GoType() reflect.Type

func (*FixedArraySchema) MarshalJSON

func (s *FixedArraySchema) MarshalJSON() ([]byte, error)

func (*FixedArraySchema) MarshalSchemer

func (s *FixedArraySchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

func (*FixedArraySchema) Valid

func (s *FixedArraySchema) Valid() bool

type FixedIntSchema

type FixedIntSchema struct {
	SchemaOptions

	Signed bool
	Bits   int // must be 8, 16, 32, or 64
}

func (*FixedIntSchema) Decode

func (s *FixedIntSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*FixedIntSchema) DecodeValue

func (s *FixedIntSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*FixedIntSchema) Encode

func (s *FixedIntSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*FixedIntSchema) EncodeValue

func (s *FixedIntSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*FixedIntSchema) GoType

func (s *FixedIntSchema) GoType() reflect.Type

func (*FixedIntSchema) MarshalJSON

func (s *FixedIntSchema) MarshalJSON() ([]byte, error)

func (*FixedIntSchema) MarshalSchemer

func (s *FixedIntSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

func (*FixedIntSchema) Valid

func (s *FixedIntSchema) Valid() bool

type FixedObjectSchema

type FixedObjectSchema struct {
	SchemaOptions
	Fields []ObjectField
}

func (*FixedObjectSchema) Decode

func (s *FixedObjectSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in v

func (*FixedObjectSchema) DecodeValue

func (s *FixedObjectSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*FixedObjectSchema) Encode

func (s *FixedObjectSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*FixedObjectSchema) EncodeValue

func (s *FixedObjectSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*FixedObjectSchema) GoType

func (s *FixedObjectSchema) GoType() reflect.Type

func (*FixedObjectSchema) MarshalJSON

func (s *FixedObjectSchema) MarshalJSON() ([]byte, error)

func (*FixedObjectSchema) MarshalSchemer

func (s *FixedObjectSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

type FixedStringSchema

type FixedStringSchema struct {
	SchemaOptions
	Length int
}

func (*FixedStringSchema) Decode

func (s *FixedStringSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*FixedStringSchema) DecodeValue

func (s *FixedStringSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*FixedStringSchema) Encode

func (s *FixedStringSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*FixedStringSchema) EncodeValue

func (s *FixedStringSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*FixedStringSchema) GoType

func (s *FixedStringSchema) GoType() reflect.Type

func (*FixedStringSchema) MarshalJSON

func (s *FixedStringSchema) MarshalJSON() ([]byte, error)

func (*FixedStringSchema) MarshalSchemer

func (s *FixedStringSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

func (*FixedStringSchema) Valid

func (s *FixedStringSchema) Valid() bool

type FloatSchema

type FloatSchema struct {
	SchemaOptions
	Bits int // must be 32 or 64
}

func (*FloatSchema) Decode

func (s *FloatSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*FloatSchema) DecodeValue

func (s *FloatSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*FloatSchema) Encode

func (s *FloatSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*FloatSchema) EncodeValue

func (s *FloatSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*FloatSchema) GoType

func (s *FloatSchema) GoType() reflect.Type

func (*FloatSchema) MarshalJSON

func (s *FloatSchema) MarshalJSON() ([]byte, error)

func (*FloatSchema) MarshalSchemer

func (s *FloatSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

func (*FloatSchema) Valid

func (s *FloatSchema) Valid() bool

type Marshaler

type Marshaler interface {
	MarshalSchemer() ([]byte, error)
}

Marshaler is an interface implemented by a schema, allowing it to encode itself into a portable binary format

type ObjectField

type ObjectField struct {
	Aliases []string
	Schema  Schema
}

type Schema

type Schema interface {
	// Encode uses the schema to write the encoded value of i to the output
	// stream
	Encode(w io.Writer, i interface{}) error

	// EncodeValue uses the schema to write the encoded value of v to the output
	// stream
	EncodeValue(w io.Writer, v reflect.Value) error

	// Decode uses the schema to read the next encoded value from the input
	// stream and stores it in i
	Decode(r io.Reader, i interface{}) error

	// DecodeValue uses the schema to read the next encoded value from the input
	// stream and stores it in v
	DecodeValue(r io.Reader, v reflect.Value) error

	// GoType returns the default Go type that represents the schema
	GoType() reflect.Type
}

Schema is an interface that encodes and decodes data of a specific type

func DecodeSchema

func DecodeSchema(r io.Reader) (Schema, error)

DecodeSchema decodes a binary encoded schema by reading from r No internal buffering is used when reading from r

func DecodeSchemaJSON

func DecodeSchemaJSON(r io.Reader) (Schema, error)

DecodeSchemaJSON takes a buffer of JSON data and parses it to create a schema The input stream r is read in its entirety before the JSON is decoded.

func SchemaOf

func SchemaOf(i interface{}) (Schema, error)

SchemaOf returns a Schema for the specified interface value. If i is a pointer or interface type, the value of the pointer/interface is used to generate the Schema. If i is nil, an zero-field FixedObjectSchema is returned.

func SchemaOfType

func SchemaOfType(t reflect.Type) (Schema, error)

SchemaOfType returns a Schema for the specified Go type

type SchemaGenerator

type SchemaGenerator interface {
	SchemaOfType(t reflect.Type) (Schema, error)
	DecodeSchema(r io.Reader) (Schema, error)
	DecodeSchemaJSON(r io.Reader) (Schema, error)
}

SchemaGenerator is an interface implemented by custom schema generators. When Register is called on a SchemaGenerator, the global SchemaOf, DecodeSchema, and DecodeSchemaJSON functions will call the identically named method on each schema generator to determine if a custom schema should be returned. If a SchemaGenerator cannot return a Schema for a specific type, it should return nil, nil. If all schema generators return a nil Schema or if Register is never called, then the built-in logic for returning a Schema is used.

type SchemaOptions

type SchemaOptions struct {
	// contains filtered or unexported fields
}

SchemaOptions are options common to each Schema

func (*SchemaOptions) Nullable

func (o *SchemaOptions) Nullable() bool

Nullable indicates that the value encoded or decoded can be either the underlying type or a null value

func (*SchemaOptions) SetNullable

func (o *SchemaOptions) SetNullable(n bool)

SetNullable sets the nullable flag

func (*SchemaOptions) SetWeakDecoding

func (o *SchemaOptions) SetWeakDecoding(w bool)

SetWeakDecoding sets the weak decoding flag

func (*SchemaOptions) WeakDecoding

func (o *SchemaOptions) WeakDecoding() bool

WeakDecoding indicates that the schema should be more lenient when decoding (i.e. decoding a boolean to a string). See README for details.

type StructTag

type StructTag struct {
	FieldAliases    []string // list of names of fields. This comes from the name of the field in the struct, and also struct tags
	FieldAliasesSet bool     // if true, struct tags are present on this field
	Nullable        bool     // is this field nullable?
	NullableSet     bool     // if true, then the null struct tags is present on this field
	WeakDecoding    bool     // does this field allow weak decoding?
	WeakDecodingSet bool     // if true, weak decoding was present in the struct tag for this field
}

StructTag represents information that can be parsed from a schemer struct tag

func ParseStructTag

func ParseStructTag(s string) (tag StructTag)

ParseStructTag parses a struct tag string and returns a decoded StructTag the format of the tag must be: tag := alias? ("," option)* alias := "-" |

identifier |
"[" identifier ("," identifier)* "]"

option := "!" ? ( "weak" | "null" ) If the

type VarArraySchema

type VarArraySchema struct {
	SchemaOptions

	Element Schema
}

func (*VarArraySchema) Decode

func (s *VarArraySchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*VarArraySchema) DecodeValue

func (s *VarArraySchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*VarArraySchema) Encode

func (s *VarArraySchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*VarArraySchema) EncodeValue

func (s *VarArraySchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*VarArraySchema) GoType

func (s *VarArraySchema) GoType() reflect.Type

func (*VarArraySchema) MarshalJSON

func (s *VarArraySchema) MarshalJSON() ([]byte, error)

func (*VarArraySchema) MarshalSchemer

func (s *VarArraySchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

type VarIntSchema

type VarIntSchema struct {
	SchemaOptions
	Signed bool
}

func (*VarIntSchema) Decode

func (s *VarIntSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*VarIntSchema) DecodeValue

func (s *VarIntSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*VarIntSchema) Encode

func (s *VarIntSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*VarIntSchema) EncodeValue

func (s *VarIntSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*VarIntSchema) GoType

func (s *VarIntSchema) GoType() reflect.Type

func (*VarIntSchema) MarshalJSON

func (s *VarIntSchema) MarshalJSON() ([]byte, error)

func (*VarIntSchema) MarshalSchemer

func (s *VarIntSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

type VarObjectSchema

type VarObjectSchema struct {
	SchemaOptions
	Key   Schema
	Value Schema
}

func (*VarObjectSchema) Decode

func (s *VarObjectSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*VarObjectSchema) DecodeValue

func (s *VarObjectSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*VarObjectSchema) Encode

func (s *VarObjectSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*VarObjectSchema) EncodeValue

func (s *VarObjectSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output streamm

func (*VarObjectSchema) GoType

func (s *VarObjectSchema) GoType() reflect.Type

func (*VarObjectSchema) MarshalJSON

func (s *VarObjectSchema) MarshalJSON() ([]byte, error)

func (*VarObjectSchema) MarshalSchemer

func (s *VarObjectSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

type VarStringSchema

type VarStringSchema struct {
	SchemaOptions
}

func (*VarStringSchema) Decode

func (s *VarStringSchema) Decode(r io.Reader, i interface{}) error

Decode uses the schema to read the next encoded value from the input stream and store it in i

func (*VarStringSchema) DecodeValue

func (s *VarStringSchema) DecodeValue(r io.Reader, v reflect.Value) error

DecodeValue uses the schema to read the next encoded value from the input stream and store it in v

func (*VarStringSchema) Encode

func (s *VarStringSchema) Encode(w io.Writer, i interface{}) error

Encode uses the schema to write the encoded value of i to the output stream

func (*VarStringSchema) EncodeValue

func (s *VarStringSchema) EncodeValue(w io.Writer, v reflect.Value) error

EncodeValue uses the schema to write the encoded value of v to the output stream

func (*VarStringSchema) GoType

func (s *VarStringSchema) GoType() reflect.Type

func (*VarStringSchema) MarshalJSON

func (s *VarStringSchema) MarshalJSON() ([]byte, error)

func (*VarStringSchema) MarshalSchemer

func (s *VarStringSchema) MarshalSchemer() ([]byte, error)

Bytes encodes the schema in a portable binary format

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL