plist

package module
v0.0.0-...-a560107 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2019 License: BSD-2-Clause-Views, BSD-3-Clause Imports: 23 Imported by: 2

README

plist - A pure Go property list transcoder coverage report

INSTALL

$ go get howett.net/plist

FEATURES

  • Supports encoding/decoding property lists (Apple XML, Apple Binary, OpenStep and GNUStep) from/to arbitrary Go types

USE

package main
import (
	"howett.net/plist"
	"os"
)
func main() {
	encoder := plist.NewEncoder(os.Stdout)
	encoder.Encode(map[string]string{"hello": "world"})
}

Documentation

Overview

Package plist implements encoding and decoding of Apple's "property list" format. Property lists come in three sorts: plain text (GNUStep and OpenStep), XML and binary. plist supports all of them. The mapping between property list and Go objects is described in the documentation for the Marshal and Unmarshal functions.

Example
package main

import (
	"encoding/base64"
	"fmt"

	"howett.net/plist"
)

type Base64String string

func (e Base64String) MarshalPlist() (interface{}, error) {
	return base64.StdEncoding.EncodeToString([]byte(e)), nil
}

func (e *Base64String) UnmarshalPlist(unmarshal func(interface{}) error) error {
	var b64 string
	if err := unmarshal(&b64); err != nil {
		return err
	}

	bytes, err := base64.StdEncoding.DecodeString(b64)
	if err != nil {
		return err
	}

	*e = Base64String(bytes)
	return nil
}

func main() {
	s := Base64String("Dustin")

	data, err := plist.Marshal(&s, plist.OpenStepFormat)
	if err != nil {
		panic(err)
	}

	fmt.Println("Property List:", string(data))

	var decoded Base64String
	_, err = plist.Unmarshal(data, &decoded)
	if err != nil {
		panic(err)
	}

	fmt.Println("Raw Data:", string(decoded))

}
Output:

Property List: RHVzdGlu
Raw Data: Dustin

Index

Examples

Constants

View Source
const (
	// Used by Decoder to represent an invalid property list.
	InvalidFormat int = 0

	// Used to indicate total abandon with regards to Encoder's output format.
	AutomaticFormat = 0

	XMLFormat      = 1
	BinaryFormat   = 2
	OpenStepFormat = 3
	GNUStepFormat  = 4
)

Property list format constants

Variables

View Source
var FormatNames = map[int]string{
	InvalidFormat:  "unknown/invalid",
	XMLFormat:      "XML",
	BinaryFormat:   "Binary",
	OpenStepFormat: "OpenStep",
	GNUStepFormat:  "GNUStep",
}

Functions

func Marshal

func Marshal(v interface{}, format int) ([]byte, error)

Marshal returns the property list encoding of v in the specified format.

Pass AutomaticFormat to allow the library to choose the best encoding (currently BinaryFormat).

Marshal traverses the value v recursively. Any nil values encountered, other than the root, will be silently discarded as the property list format bears no representation for nil values.

Strings, integers of varying size, floats and booleans are encoded unchanged. Strings bearing non-ASCII runes will be encoded differently depending upon the property list format: UTF-8 for XML property lists and UTF-16 for binary property lists.

Slice and Array values are encoded as property list arrays, except for []byte values, which are encoded as data.

Map values encode as dictionaries. The map's key type must be string; there is no provision for encoding non-string dictionary keys.

Struct values are encoded as dictionaries, with only exported fields being serialized. Struct field encoding may be influenced with the use of tags. The tag format is:

`plist:"<key>[,flags...]"`

The following flags are supported:

omitempty    Only include the field if it is not set to the zero value for its type.

If the key is "-", the field is ignored.

Anonymous struct fields are encoded as if their exported fields were exposed via the outer struct.

Pointer values encode as the value pointed to.

Channel, complex and function values cannot be encoded. Any attempt to do so causes Marshal to return an error.

Example (Gnustep)
type sparseBundleHeader struct {
	InfoDictionaryVersion string `plist:"CFBundleInfoDictionaryVersion"`
	BandSize              uint64 `plist:"band-size"`
	BackingStoreVersion   int    `plist:"bundle-backingstore-version"`
	DiskImageBundleType   string `plist:"diskimage-bundle-type"`
	Size                  uint64 `plist:"size"`
}
data := &sparseBundleHeader{
	InfoDictionaryVersion: "6.0",
	BandSize:              8388608,
	Size:                  4 * 1048576 * 1024 * 1024,
	DiskImageBundleType:   "com.apple.diskimage.sparsebundle",
	BackingStoreVersion:   1,
}

plist, err := MarshalIndent(data, GNUStepFormat, "\t")
if err != nil {
	fmt.Println(err)
}
fmt.Println(string(plist))
Output:

{
	CFBundleInfoDictionaryVersion = 6.0;
	band-size = <*I8388608>;
	bundle-backingstore-version = <*I1>;
	diskimage-bundle-type = com.apple.diskimage.sparsebundle;
	size = <*I4398046511104>;
}
Example (Xml)
type sparseBundleHeader struct {
	InfoDictionaryVersion string `plist:"CFBundleInfoDictionaryVersion"`
	BandSize              uint64 `plist:"band-size"`
	BackingStoreVersion   int    `plist:"bundle-backingstore-version"`
	DiskImageBundleType   string `plist:"diskimage-bundle-type"`
	Size                  uint64 `plist:"size"`
}
data := &sparseBundleHeader{
	InfoDictionaryVersion: "6.0",
	BandSize:              8388608,
	Size:                  4 * 1048576 * 1024 * 1024,
	DiskImageBundleType:   "com.apple.diskimage.sparsebundle",
	BackingStoreVersion:   1,
}

plist, err := MarshalIndent(data, XMLFormat, "\t")
if err != nil {
	fmt.Println(err)
}
fmt.Println(string(plist))
Output:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>CFBundleInfoDictionaryVersion</key>
		<string>6.0</string>
		<key>band-size</key>
		<integer>8388608</integer>
		<key>bundle-backingstore-version</key>
		<integer>1</integer>
		<key>diskimage-bundle-type</key>
		<string>com.apple.diskimage.sparsebundle</string>
		<key>size</key>
		<integer>4398046511104</integer>
	</dict>
</plist>

func MarshalIndent

func MarshalIndent(v interface{}, format int, indent string) ([]byte, error)

MarshalIndent works like Marshal, but each property list element begins on a new line and is preceded by one or more copies of indent according to its nesting depth.

func Unmarshal

func Unmarshal(data []byte, v interface{}) (format int, err error)

Unmarshal parses a property list document and stores the result in the value pointed to by v.

Unmarshal uses the inverse of the type encodings that Marshal uses, allocating heap-borne types as necessary.

When given a nil pointer, Unmarshal allocates a new value for it to point to.

To decode property list values into an interface value, Unmarshal decodes the property list into the concrete value contained in the interface value. If the interface value is nil, Unmarshal stores one of the following in the interface value:

string, bool, uint64, float64
plist.UID for "CoreFoundation Keyed Archiver UIDs" (convertible to uint64)
[]byte, for plist data
[]interface{}, for plist arrays
map[string]interface{}, for plist dictionaries

If a property list value is not appropriate for a given value type, Unmarshal aborts immediately and returns an error.

As Go does not support 128-bit types, and we don't want to pretend we're giving the user integer types (as opposed to secretly passing them structs), Unmarshal will drop the high 64 bits of any 128-bit integers encoded in binary property lists. (This is important because CoreFoundation serializes some large 64-bit values as 128-bit values with an empty high half.)

When Unmarshal encounters an OpenStep property list, it will enter a relaxed parsing mode: OpenStep property lists can only store plain old data as strings, so we will attempt to recover integer, floating-point, boolean and date values wherever they are necessary. (for example, if Unmarshal attempts to unmarshal an OpenStep property list into a time.Time, it will try to parse the string it receives as a time.)

Unmarshal returns the detected property list format and an error, if any.

Types

type Decoder

type Decoder struct {
	// the format of the most-recently-decoded property list
	Format int
	// contains filtered or unexported fields
}

A Decoder reads a property list from an input stream.

func NewDecoder

func NewDecoder(r io.ReadSeeker) *Decoder

NewDecoder returns a Decoder that reads property list elements from a stream reader, r. NewDecoder requires a Seekable stream for the purposes of file type detection.

func (*Decoder) Decode

func (p *Decoder) Decode(v interface{}) (err error)

Decode works like Unmarshal, except it reads the decoder stream to find property list elements.

After Decoding, the Decoder's Format field will be set to one of the plist format constants.

Example
type sparseBundleHeader struct {
	InfoDictionaryVersion string `plist:"CFBundleInfoDictionaryVersion"`
	BandSize              uint64 `plist:"band-size"`
	BackingStoreVersion   int    `plist:"bundle-backingstore-version"`
	DiskImageBundleType   string `plist:"diskimage-bundle-type"`
	Size                  uint64 `plist:"size"`
}

buf := bytes.NewReader([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>CFBundleInfoDictionaryVersion</key>
		<string>6.0</string>
		<key>band-size</key>
		<integer>8388608</integer>
		<key>bundle-backingstore-version</key>
		<integer>1</integer>
		<key>diskimage-bundle-type</key>
		<string>com.apple.diskimage.sparsebundle</string>
		<key>size</key>
		<integer>4398046511104</integer>
	</dict>
</plist>`))

var data sparseBundleHeader
decoder := NewDecoder(buf)
err := decoder.Decode(&data)
if err != nil {
	fmt.Println(err)
}
fmt.Println(data)
Output:

{6.0 8388608 1 com.apple.diskimage.sparsebundle 4398046511104}

type Encoder

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

An Encoder writes a property list to an output stream.

func NewBinaryEncoder

func NewBinaryEncoder(w io.Writer) *Encoder

NewBinaryEncoder returns an Encoder that writes a binary property list to w.

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder returns an Encoder that writes an XML property list to w.

func NewEncoderForFormat

func NewEncoderForFormat(w io.Writer, format int) *Encoder

NewEncoderForFormat returns an Encoder that writes a property list to w in the specified format. Pass AutomaticFormat to allow the library to choose the best encoding (currently BinaryFormat).

func (*Encoder) Encode

func (p *Encoder) Encode(v interface{}) (err error)

Encode writes the property list encoding of v to the stream.

Example
type sparseBundleHeader struct {
	InfoDictionaryVersion string `plist:"CFBundleInfoDictionaryVersion"`
	BandSize              uint64 `plist:"band-size"`
	BackingStoreVersion   int    `plist:"bundle-backingstore-version"`
	DiskImageBundleType   string `plist:"diskimage-bundle-type"`
	Size                  uint64 `plist:"size"`
}
data := &sparseBundleHeader{
	InfoDictionaryVersion: "6.0",
	BandSize:              8388608,
	Size:                  4 * 1048576 * 1024 * 1024,
	DiskImageBundleType:   "com.apple.diskimage.sparsebundle",
	BackingStoreVersion:   1,
}

buf := &bytes.Buffer{}
encoder := NewEncoder(buf)
err := encoder.Encode(data)
if err != nil {
	fmt.Println(err)
}
fmt.Println(buf.String())
Output:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>band-size</key><integer>8388608</integer><key>bundle-backingstore-version</key><integer>1</integer><key>diskimage-bundle-type</key><string>com.apple.diskimage.sparsebundle</string><key>size</key><integer>4398046511104</integer></dict></plist>

func (*Encoder) Indent

func (p *Encoder) Indent(indent string)

Indent turns on pretty-printing for the XML and Text property list formats. Each element begins on a new line and is preceded by one or more copies of indent according to its nesting depth.

type Marshaler

type Marshaler interface {
	MarshalPlist() (interface{}, error)
}

Marshaler is the interface implemented by types that can marshal themselves into valid property list objects. The returned value is marshaled in place of the original value implementing Marshaler

If an error is returned by MarshalPlist, marshaling stops and the error is returned.

type UID

type UID uint64

A UID represents a unique object identifier. UIDs are serialized in a manner distinct from that of integers.

UIDs cannot be serialized in OpenStepFormat or GNUStepFormat property lists.

type Unmarshaler

type Unmarshaler interface {
	UnmarshalPlist(unmarshal func(interface{}) error) error
}

Unmarshaler is the interface implemented by types that can unmarshal themselves from property list objects. The UnmarshalPlist method receives a function that may be called to unmarshal the original property list value into a field or variable.

It is safe to call the unmarshal function more than once.

Directories

Path Synopsis
cmd
ply

Jump to

Keyboard shortcuts

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