Documentation ¶
Overview ¶
Example (CustomMarshalOscript) ¶
package main import ( "fmt" "log" "strings" "github.com/itcomusic/ot/pkg/oscript" ) type Animal int const ( Unknown Animal = iota Gopher Zebra ) func (a *Animal) UnmarshalOscript(b []byte) error { var s string if err := oscript.Unmarshal(b, &s); err != nil { return err } switch strings.ToLower(s) { default: *a = Unknown case "gopher": *a = Gopher case "zebra": *a = Zebra } return nil } func (a Animal) MarshalOscript() ([]byte, error) { var s string switch a { default: s = "unknown" case Gopher: s = "gopher" case Zebra: s = "zebra" } return oscript.Marshal(s) } func main() { blob := `{'gopher','armadillo','zebra','unknown','gopher','bee','gopher','zebra'}` var zoo []Animal if err := oscript.Unmarshal([]byte(blob), &zoo); err != nil { log.Fatal(err) } census := make(map[Animal]int) for _, animal := range zoo { census[animal]++ } fmt.Printf("Zoo Census:\n* Gophers: %d\n* Zebras: %d\n* Unknown: %d\n", census[Gopher], census[Zebra], census[Unknown]) }
Output: Zoo Census: * Gophers: 3 * Zebras: 2 * Unknown: 3
Index ¶
- func Compact(dst *bytes.Buffer, src []byte) error
- func Marshal(v interface{}) ([]byte, error)
- func Unmarshal(data []byte, v interface{}) error
- func Valid(data []byte) bool
- type Buffer
- type Decoder
- type Delim
- type Encoder
- type Error
- type InvalidUnmarshalError
- type M
- type Marshaler
- type MarshalerBuf
- type MarshalerError
- type SDOName
- type SyntaxError
- type Token
- type UnmarshalTypeError
- type Unmarshaler
- type UnsupportedTypeError
- type UnsupportedValueError
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Compact ¶
Compact appends to dst the oscript-encoded src with insignificant space characters elided.
func Marshal ¶
The encoding of each struct field can be customized by the format string stored under the "oscript" key in the struct field's tag. The format string gives the name of the field, possibly followed by a comma-separated list of options. The name may be empty in order to specify options without overriding the default field name.
The "omitempty" option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.
As a special case, if the field tag is "-", the field is always omitted. Note that a field with name "-" can still be generated using the tag "-,".
Anonymous struct fields are usually marshaled as if their inner exported fields were fields in the outer struct, subject to the usual Go visibility rules amended as described in the next paragraph. An anonymous struct field with a name given in its Oscript tag is treated as having that name, rather than being anonymous. An anonymous struct field of interface type is treated the same as having that type as its name, rather than being anonymous.
The Go visibility rules for struct fields are amended for Oscript when deciding which field to marshal or unmarshal. If there are multiple fields at the same level, and that level is the least nested (and would therefore be the nesting level selected by the usual Go rules), the following extra rules apply:
1) Of those fields, if any are Oscript-tagged, only tagged fields are considered, even if there are multiple untagged fields that would otherwise conflict.
2) If there is exactly one field (tagged or not according to the first rule), that is selected.
3) Otherwise there are multiple fields, and all are ignored; no error occurs.
Map values encode as oscript objects: A<1,?,'key'=value>. The map's key type must either be a string, an integer type, or implement encoding.TextMarshaler.
- string keys are used directly
- encoding.TextMarshalers are marshaled
- integer keys are converted to strings
Pointer values encode as the value pointed to. A nil pointer encodes as the undefined Oscript value.
Interface values encode as the value contained in the interface. A nil interface value encodes as the undefined Oscript value.
Channel, complex, and function values cannot be encoded in oscript. Attempting to encode such a value causes Marshal to return an UnsupportedTypeError.
Oscript cannot represent cyclic data structures and Marshal does not handle them. Passing cyclic structures to Marshal will result in an infinite recursion.
Example ¶
package main import ( "fmt" "os" "github.com/itcomusic/ot/pkg/oscript" ) func main() { type ColorGroup struct { ID int Name string Colors []string } group := ColorGroup{ ID: 1, Name: "Reds", Colors: []string{"Crimson", "Red", "Ruby", "Maroon"}, } b, err := oscript.Marshal(group) if err != nil { fmt.Println("error:", err) } os.Stdout.Write(b) }
Output: A<1,?,'ID'=1,'Name'='Reds','Colors'={'Crimson','Red','Ruby','Maroon'}>
func Unmarshal ¶
The oscript undefined value unmarshals into an interface, map, pointer, or slice by setting that Go value to nil. Because undefined is often used in oscript to mean `not present' unmarshaling a Oscript undefined into any other Go type has no effect on the value and produces no error.
When unmarshaling quoted strings, invalid UTF-8 or invalid UTF-16 surrogate pairs are not treated as an error. Instead, they are replaced by the Unicode replacement character U+FFFD.
Example ¶
package main import ( "fmt" "github.com/itcomusic/ot/pkg/oscript" ) func main() { var oscriptBlob = []byte(`{ A<1,?,'Name'= 'Platypus', 'Order'= 'Monotremata'>, A<1,?,'Name'= 'Quoll', 'Order'= 'Dasyuromorphia'> }`) type Animal struct { Name string Order string } var animals []Animal err := oscript.Unmarshal(oscriptBlob, &animals) if err != nil { fmt.Println("error:", err) } fmt.Printf("%+v", animals) }
Output: [{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]
Types ¶
type Buffer ¶
type Buffer interface { WriteString(s string) (int, error) WriteStringValue(s string) WriteByte(b byte) error WriteEncode(v interface{}) }
Buffer is the interface implemented by internal encodeState.
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
A Decoder reads and decodes Oscript values from an input stream.
Example ¶
This example uses a Decoder to decode a stream of distinct Oscript values.
package main import ( "fmt" "io" "log" "strings" "github.com/itcomusic/ot/pkg/oscript" ) func main() { const oscriptStream = ` A<1,?,'Name'= 'Ed', 'Text'= 'Knock knock.'> A<1,?,'Name'= 'Sam', 'Text'= 'Who\'s there?'> A<1,?,'Name'= 'Ed', 'Text'= 'Go fmt.'> A<1,?,'Name'= 'Sam', 'Text'= 'Go fmt who?'> A<1,?,'Name'= 'Ed', 'Text'= 'Go fmt yourself!'> ` type Message struct { Name, Text string } dec := oscript.NewDecoder(strings.NewReader(oscriptStream)) for { var m Message if err := dec.Decode(&m); err == io.EOF { break } else if err != nil { log.Fatal(err) } fmt.Printf("%s: %s\n", m.Name, m.Text) } }
Output: Ed: Knock knock. Sam: Who's there? Ed: Go fmt. Sam: Go fmt who? Ed: Go fmt yourself!
func NewDecoder ¶
NewDecoder returns a new decoder that reads from r.
The decoder introduces its own buffering and may read data from r beyond the oscript values requested.
func (*Decoder) Buffered ¶
Buffered returns a reader of the data remaining in the Decoder's buffer. The reader is valid until the next call to Decode.
func (*Decoder) Decode ¶
Decode reads the next Oscript-encoded value from its input and stores it in the value pointed to by v.
See the documentation for Unmarshal for details about the conversion of Oscript into a Go value.
Example (Stream) ¶
This example uses a Decoder to decode a streaming array of Oscript objects.
package main import ( "fmt" "log" "strings" "github.com/itcomusic/ot/pkg/oscript" ) func main() { const oscriptStream = ` { A<1,?,'Name'= 'Ed', 'Text'= 'Knock knock.'>, A<1,?,'Name'= 'Sam', 'Text'= 'Who\'s there?'>, A<1,?,'Name'= 'Ed', 'Text'= 'Go fmt.'>, A<1,?,'Name'= 'Sam', 'Text'= 'Go fmt who?'>, A<1,?,'Name'= 'Ed', 'Text'= 'Go fmt yourself!'> } ` type Message struct { Name, Text string } dec := oscript.NewDecoder(strings.NewReader(oscriptStream)) // read open bracket t, err := dec.Token() if err != nil { log.Fatal(err) } fmt.Printf("%T: %v\n", t, t) // while the array contains values for dec.More() { var m Message // decode an array value (Message) err := dec.Decode(&m) if err != nil { log.Fatal(err) } fmt.Printf("%v: %v\n", m.Name, m.Text) } // read closing bracket t, err = dec.Token() if err != nil { log.Fatal(err) } fmt.Printf("%T: %v\n", t, t) }
Output: oscript.Delim: { Ed: Knock knock. Sam: Who's there? Ed: Go fmt. Sam: Go fmt who? Ed: Go fmt yourself! oscript.Delim: }
func (*Decoder) DisallowUnknownFields ¶
func (dec *Decoder) DisallowUnknownFields()
DisallowUnknownFields causes the Decoder to return an error when the destination is a struct and the input contains object keys which do not match any non-ignored, exported fields in the destination.
func (*Decoder) More ¶
More reports whether there is another element in the current array or object being parsed.
func (*Decoder) Token ¶
Token returns the next Oscript token in the input stream. At the end of the input stream, Token returns nil, io.EOF.
Token guarantees that the delimiters A<1,? > { } it returns are properly nested and matched: if Token encounters an unexpected delimiter in the input, it will return an error.
The input stream consists of basic Oscript values—bool, string, number, and undefined—along with delimiters A<1,? > { } of type Delim to mark the start and end of arrays and objects. Commas and equally are elided.
Example ¶
This example uses a Decoder to decode a stream of distinct Oscript values.
package main import ( "fmt" "io" "log" "strings" "github.com/itcomusic/ot/pkg/oscript" ) func main() { const oscriptStream = ` A<1,?,'Message'= 'Hello', 'Array'= {1, 2, 3}, 'Undefined'= ?, 'Number'= G1.234> ` dec := oscript.NewDecoder(strings.NewReader(oscriptStream)) for { t, err := dec.Token() if err == io.EOF { break } if err != nil { log.Fatal(err) } fmt.Printf("%T: %v", t, t) if dec.More() { fmt.Printf(" (more)") } fmt.Printf("\n") } }
Output: oscript.Delim: A (more) string: Message (more) string: Hello (more) string: Array (more) oscript.Delim: { (more) int64: 1 (more) int64: 2 (more) int64: 3 oscript.Delim: } (more) string: Undefined (more) <nil>: <nil> (more) string: Number (more) float64: 1.234 oscript.Delim: >
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
An Encoder writes Oscript values to an output stream.
func NewEncoder ¶
NewEncoder returns a new encoder that writes to w.
func (*Encoder) EnableEncodeNL ¶
func (enc *Encoder) EnableEncodeNL()
EnableEncodeNL enables newline after call Encode.
type Error ¶
type Error int
Error is a error string.
func (Error) MarshalOscript ¶
MarshalOscript implements the oscript.Marshaler interface.
func (*Error) UnmarshalOscript ¶
UnmarshalOscript implements the oscript.Unmarshaler interface.
type InvalidUnmarshalError ¶
An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. (The argument to Unmarshal must be a non-nil pointer.)
func (*InvalidUnmarshalError) Error ¶
func (e *InvalidUnmarshalError) Error() string
type M ¶
type M map[string]interface{}
M is a convenient alias for a map[string]interface{} map, useful for short define For instance: script.M{"key1": 1, "key2": true}
There's no special handling for this type in addition to what's done anyway for an equivalent map type.
type Marshaler ¶
Marshaler is the interface implemented by types that can marshal themselves into valid oscript.
type MarshalerBuf ¶
MarshalerBuf is the interface implemented by types that can marshal themselves and does not require addition allocation as a Marshaller for returning []byte.
type MarshalerError ¶
func (*MarshalerError) Error ¶
func (e *MarshalerError) Error() string
type SyntaxError ¶
type SyntaxError struct { Offset int64 // error occurred after reading Offset bytes // contains filtered or unexported fields }
A SyntaxError is a description of a Oscript syntax error.
func (*SyntaxError) Error ¶
func (e *SyntaxError) Error() string
type Token ¶
type Token interface{}
A Token holds a value of one of these types:
Delim, for the four Oscript delimiters A > { } bool, for Oscript booleans number, for Oscript integers float64, for Oscript reals string, for Oscript string literals nil, for Oscript ?
type UnmarshalTypeError ¶
type UnmarshalTypeError struct { Value string // description of Oscript value - "bool", "array", "number -5" Type reflect.Type // type of Go value it could not be assigned to Offset int64 // error occurred after reading Offset bytes Struct string // name of the struct type containing the field Field string // name of the field holding the Go value }
An UnmarshalTypeError describes a Oscript value that was not appropriate for a value of a specific Go type.
func (*UnmarshalTypeError) Error ¶
func (e *UnmarshalTypeError) Error() string
type Unmarshaler ¶
Unmarshaler is the interface implemented by types that can unmarshal a Oscript description of themselves. The input can be assumed to be a valid encoding of a Oscript value. UnmarshalOscript must copy the Oscript data if it wishes to retain the data after returning.
By convention, to approximate the behavior of Unmarshal itself, Unmarshalers implement UnmarshalOscript([]byte("?")) as a no-op.
type UnsupportedTypeError ¶
An UnsupportedTypeError is returned by Marshal when attempting to encode an unsupported value type.
func (*UnsupportedTypeError) Error ¶
func (e *UnsupportedTypeError) Error() string
type UnsupportedValueError ¶
An UnsupportedValueError is returned by Marshal when attempting to encode an unsupported value.
func (*UnsupportedValueError) Error ¶
func (e *UnsupportedValueError) Error() string