tags

package
v0.0.10 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2019 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package tags provides a simple API for reading and writing to lines of tags. tags also supports iterators for efficiently reading through a stream. See the examples below for usage.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrEmptyInput               = errors.New("empty input")
	ErrInvalidRune              = errors.New("invalid rune")
	ErrMissingKeyValueSeparator = errors.New("missing key-value separator")
	ErrMissingLineSeparator     = errors.New("missing line separator")
	ErrMissingKeySerializer     = errors.New("missing key serializer")
	ErrMissingValueSerializer   = errors.New("missing value serializer")
	ErrMissingType              = errors.New("missing type")
	ErrInvalidUTF8              = errors.New("invalid utf-8")
)
View Source
var (
	DefaultType = reflect.TypeOf(map[string]string{})
)

Functions

func Marshal

func Marshal(object interface{}, keys []interface{}, expandKeys bool, keyValueSeparator string, keySerializer stringify.Stringer, valueSerializer stringify.Stringer, sorted bool, reversed bool) ([]byte, error)

Marshal formats an object into a slice of bytes of tags (aka key=value pairs) The value serializer is used to render the key and value of each pair into strings. If keys is not empty, then prints the tags in the order specifed by keys. If expandKeys is true, then adds unknown keys to the end of the list of tags. If sorted and not reversed, then the keys are sorted in alphabetical order. If sorted and reversed, then the keys are sorted in reverse alphabetical order.

Example (Map)

This example shows how to marshal a map into a line of tags.

obj := map[string]interface{}{
	"a": 1,
	"b": 2,
	"c": 3,
}
keys := make([]interface{}, 0)
b, err := Marshal(obj, keys, true, "=", stringify.NewStringer("", false, false, false), stringify.NewStringer("", false, false, false), true, false)
if err != nil {
	panic(err)
}
fmt.Println(string(b))
Output:

a=1 b=2 c=3
Example (Stuct)

This example shows how to marshal a struct into a line of tags.

in := struct {
	A string
	B string
	C string
}{A: "1", B: "2", C: "3"}
keys := make([]interface{}, 0)
keySerializer := stringify.NewStringer("", false, false, false)
valueSerializer := stringify.NewStringer("", false, false, false)
b, err := Marshal(in, keys, true, "=", keySerializer, valueSerializer, true, false)
if err != nil {
	panic(err)
}
fmt.Println(string(b))
Output:

A=1 B=2 C=3

func Read

func Read(input *ReadInput) (interface{}, error)

Read reads the lines of tags from the input Reader into the given type. If no type is given, returns a slice of type []map[string]string.

Example
in := `
	a=b
	hello="beautiful world"
	hello="beautiful \"wide\" world"
  `
out, err := Read(&ReadInput{
	Type:              reflect.TypeOf([]interface{}{}),
	Reader:            strings.NewReader(in),
	SkipLines:         0,
	SkipBlanks:        true,
	SkipComments:      false,
	KeyValueSeparator: "=",
	LineSeparator:     []byte("\n")[0],
	DropCR:            true,
	Comment:           "",
})
if err != nil {
	panic(err)
}
fmt.Println(out)
Output:

[map[a:b] map[hello:beautiful world] map[hello:beautiful "wide" world]]

func Unmarshal

func Unmarshal(b []byte, keyValueSeparator rune) (interface{}, error)

Unmarshal parses a slice of bytes into an object using a few simple type inference rules. This package is useful when your program needs to parse data, that you have no a priori awareness of its structure or type. If no input is given, then returns ErrEmptyInput. If the first rune is invalid, then returns ErrInvalidRune.

Example (Map)

This example shows you can unmarshal a line of tags into a map.

str := "a=1 b=2 c=3"
obj, err := Unmarshal([]byte(str), '=')
if err != nil {
	panic(err)
}
fmt.Println(obj)
Output:

map[a:1 b:2 c:3]

func UnmarshalType

func UnmarshalType(b []byte, keyValueSeparator rune, outputType reflect.Type) (interface{}, error)

UnmarshalType parses a slice of bytes into an object of a given type. If no input is given, then returns ErrEmptyInput. If the first rune in the slice of bytes is invalid, then returns ErrInvalidRune.

Example (Map)

This example shows you can unmarshal a line of tags into a map.

str := "a=1 b=2 c=3"
obj, err := UnmarshalType([]byte(str), '=', reflect.TypeOf(map[string]string{}))
if err != nil {
	panic(err)
}
fmt.Println(obj)
Output:

map[a:1 b:2 c:3]

func Write

func Write(input *WriteInput) error

Write writes the given object(s) as lines of tags. If the type of the input object is of kind Array or Slice, then writes each object on its own line. If the type of the input object is of kind Map or Struct, then writes a single line of tags.

Example (Map)

This example shows you can marshal a single map into a JSON object

obj := map[string]string{"a": "b", "c": "beautiful world", "d": "beautiful \"wide\" world"}
keys := make([]interface{}, 0)
keySerializer := stringify.NewStringer("", false, false, false)
valueSerializer := stringify.NewStringer("", false, false, false)

buf := new(bytes.Buffer)
err := Write(&WriteInput{
	Writer:            buf,
	Keys:              keys,
	KeyValueSeparator: "=",
	LineSeparator:     "\n",
	Object:            obj,
	KeySerializer:     keySerializer,
	ValueSerializer:   valueSerializer,
	Sorted:            true,
	Limit:             -1,
})
if err != nil {
	panic(err)
}
fmt.Println(buf.String())
Output:

a=b c="beautiful world" d="beautiful \"wide\" world"
Example (Slice)

This examples shows that you can marshal a slice of maps into lines of tags.

obj := []interface{}{
	map[string]interface{}{
		"a": 1,
		"b": 2,
		"c": 3,
	},
	map[string]interface{}{
		"a": 4,
		"b": 5,
		"c": 6,
	},
}
keys := make([]interface{}, 0)
keySerializer := stringify.NewStringer("", false, false, false)
valueSerializer := stringify.NewStringer("", false, false, false)

buf := new(bytes.Buffer)
err := Write(&WriteInput{
	Writer:            buf,
	Keys:              keys,
	KeyValueSeparator: "=",
	LineSeparator:     "\n",
	Object:            obj,
	KeySerializer:     keySerializer,
	ValueSerializer:   valueSerializer,
	Sorted:            true,
	Limit:             -1,
})
if err != nil {
	panic(err)
}
fmt.Println(buf.String())
Output:

a=1 b=2 c=3
a=4 b=5 c=6

Types

type ErrInvalidKind

type ErrInvalidKind struct {
	Value    reflect.Type
	Expected []reflect.Kind
}

func (ErrInvalidKind) Error

func (e ErrInvalidKind) Error() string

Error returns the error formatted as a string.

type Flusher

type Flusher interface {
	Flush() error
}

Flusher interfaces is a simple interface that wraps the Flush() function.

type Iterator

type Iterator struct {
	Scanner           scanner.Scanner // the scanner that splits the underlying stream of bytes
	Type              reflect.Type
	KeyValueSeparator rune   // the key value separator
	Comment           string // The comment line prefix.  Can be any string.
	SkipBlanks        bool   // Skip blank lines.  If false, Next() returns a blank line as (nil, nil).  If true, Next() simply skips forward until it finds a non-blank line.
	SkipComments      bool   // Skip commented lines.  If false, Next() returns a commented line as (nil, nil).  If true, Next() simply skips forward until it finds a non-commented line.
	Limit             int    // Limit the number of objects to read and return from the underlying stream.
	Count             int    // The current count of the number of objects read.
}

Iterator iterates trough a stream of bytes returning a new object on each call of Next() until it reaches the end and returns io.EOF.

func NewIterator

func NewIterator(input *NewIteratorInput) (*Iterator, error)

NewIterator returns a new JSON Lines (aka jsonl) Iterator base on the given input.

func (*Iterator) Next

func (it *Iterator) Next() (interface{}, error)

Next reads from the underlying reader and returns the next object and error, if any. If a blank line is found and SkipBlanks is false, then returns (nil, nil). If a commented line is found and SkipComments is false, then returns (nil, nil). When the input stream is exhausted, returns (nil, io.EOF).

type NewIteratorInput

type NewIteratorInput struct {
	Reader            io.Reader
	Type              reflect.Type
	SkipLines         int    // Skip a given number of lines at the beginning of the stream.
	SkipBlanks        bool   // Skip blank lines.  If false, Next() returns a blank line as (nil, nil).  If true, Next() simply skips forward until it finds a non-blank line.
	SkipComments      bool   // Skip commented lines.  If false, Next() returns a commented line as (nil, nil).  If true, Next() simply skips forward until it finds a non-commented line.
	Comment           string // The comment line prefix. Can be any string.
	Limit             int    // Limit the number of objects to read and return from the underlying stream.
	KeyValueSeparator string // the key value separator
	LineSeparator     byte   // The new line byte.
	DropCR            bool   // Drop carriage returns at the end of lines.
}

Input for NewIterator function.

type ReadInput

type ReadInput struct {
	Type              reflect.Type  // the output type
	Reader            io.Reader     // the underlying reader
	Keys              []interface{} // the keys to read
	SkipLines         int
	SkipBlanks        bool
	SkipComments      bool
	Comment           string // the comment prefix
	KeyValueSeparator string // the key-value separator
	LineSeparator     byte   // the line separator
	DropCR            bool   // drop carriage return
	Limit             int
}

ReadInput provides the input for the Read function.

type WriteFlusher

type WriteFlusher interface {
	io.Writer
	Flusher
}

WriterFlusher is a simple interface that wraps io.Writer and Flusher.

type WriteInput

type WriteInput struct {
	Writer            io.Writer     // the underlying writer
	Keys              []interface{} // subset of keys to print
	ExpandKeys        bool          // dynamically expand keys
	KeyValueSeparator string        // the key-value separator
	LineSeparator     string        // the line separator
	Object            interface{}   // the object to write
	KeySerializer     stringify.Stringer
	ValueSerializer   stringify.Stringer
	Sorted            bool // sort keys
	Reversed          bool
	Limit             int
}

WriteInput provides the input for the Write function.

type Writer

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

Writer formats and writes objects to the underlying writer as JSON Lines (aka jsonl).

func NewWriter

func NewWriter(w io.Writer, keys []interface{}, expandKeys bool, keyValueSeparator string, lineSeparator string, keySerializer stringify.Stringer, valueSerializer stringify.Stringer, sorted bool, reversed bool) *Writer

NewWriter returns a writer for formating and writing objets to the underlying writer as JSON Lines (aka jsonl).

func (*Writer) Close added in v0.0.9

func (w *Writer) Close() error

Close closes the underlying writer, if it has a Close method.

func (*Writer) Flush

func (w *Writer) Flush() error

Flush flushes the underlying writer, if it has a Flush method. This writer itself does no buffering.

func (*Writer) WriteObject

func (w *Writer) WriteObject(obj interface{}) error

WriteObject formats and writes a single object to the underlying writer as JSON and appends the writer's line separator.

func (*Writer) WriteObjects

func (w *Writer) WriteObjects(objects interface{}) error

WriteObjects formats and writes the given objets to the underlying writer as JSON lines and separates the objects using the writer's line separator.

Jump to

Keyboard shortcuts

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