hy

package module
v0.0.0-...-1338e7e Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2016 License: MIT Imports: 14 Imported by: 2

README

hy: hierarchical files

CircleCI codecov Go Report Card GoDoc License MIT

TODO

  • Improve memory efficiency (currently loads everything eagerly in-memory, should use readers and (de)coders rather than []byte and marshalers).
  • Add test cases for all failure modes.
    • Attempt to specify a directory for a struct field.
    • SpecialMap has wrong method signatures.
  • Make analysis concurrent.
  • Make writing concurrent.
  • Make reading concurrent.
  • Add options for default path names:
    • lowerCamelCase
    • CamelCase
    • snake_case
    • lowercaseonly
  • On write, need to pick:
    • Fail if ID field not matching key or index?
    • Overwrite ID with current key or index?
    • Elide ID field from output altogether? (This should be the default, so it only matters in memory.)
    • Other?

Documentation

Index

Constants

This section is empty.

Variables

View Source
var JSONWriter = FileMarshaler{
	MarshalFunc:   json.Marshal,
	UnmarshalFunc: json.Unmarshal,
	FileExtension: "json",
	RootFileName:  "_",
}

JSONWriter is a FileWriter configured to marshal JSON.

View Source
var NodeTypes = []Node{
	&SpecialMapNode{}, &StructNode{}, &FileNode{}, &MapNode{}, &SliceNode{},
}

NodeTypes contains the set of nodes types in order of preference. Earlier types will be detected before later ones.

Functions

This section is empty.

Types

type Codec

type Codec struct {
	// MarshalFunc is used to write file data. The signature matches
	// json.Marshal as well as many other standard marshalers.
	MarshalFunc func(interface{}) ([]byte, error)
	// UnmarshalFunc is used to read file data. The signature matches
	// json.Unmarshal as well as many other standard unmarshalers.
	UnmarshalFunc func([]byte, interface{}) error
	// FileExtension is the extension to use for reading and writing files. It
	// must not be empty.
	FileExtension,

	RootFileName string
	// contains filtered or unexported fields
}

Codec provides the primary encoding and decoding facility of this package. Codecs should be re-used to take advantage of their caching of reflection data.

func NewCodec

func NewCodec(configure ...func(*Codec)) *Codec

NewCodec creates a new codec.

func (*Codec) Analyse

func (c *Codec) Analyse(root interface{}) (Node, error)

Analyse analyses a tree starting at root.

func (*Codec) NewNode

func (c *Codec) NewNode(parent Node, id NodeID, field *FieldInfo) (*Node, error)

NewNode creates a new node.

func (*Codec) Read

func (c *Codec) Read(prefix string, root interface{}) error

func (*Codec) Write

func (c *Codec) Write(prefix string, root interface{}) error

type DirNodeBase

type DirNodeBase struct {
	NodeBase
	ElemNode *Node
}

A DirNodeBase is the base type for a node stored in a directory.

func (*DirNodeBase) AnalyseElemNode

func (n *DirNodeBase) AnalyseElemNode(parent Node, c *Codec) error

AnalyseElemNode sets the element node for this directory-bound node.

type FieldInfo

type FieldInfo struct {
	Name, FieldName, PathName, KeyField, GetKeyName, SetKeyName string
	// Type is the type of this fields.
	Type,

	KeyType,

	ElemType reflect.Type
	// GetKeyFunc is a function getting the key from this map or slice's element.
	GetKeyFunc,

	SetKeyFunc reflect.Value
	// Tag is the parsed hy tag.
	Tag Tag
	// Ignore indicates this field should not be written or read by hy.
	Ignore,

	IsField,

	IsString,

	AutoFieldName,

	IsDir,

	AutoPathName,

	OmitEmpty bool
}

FieldInfo is information about a field.

func NewFieldInfo

func NewFieldInfo(f reflect.StructField) (*FieldInfo, error)

NewFieldInfo creates a new FieldInfo, analysing the tag and checking the tag's named ID field or ID get/set methods for consistency.

func (*FieldInfo) Validate

func (fi *FieldInfo) Validate() error

Validate returns any validation errors with this FieldInfo.

type FileMarshaler

type FileMarshaler struct {
	// MarshalFunc is called to marshal values to bytes.
	MarshalFunc func(interface{}) ([]byte, error)
	// UnmarshalFunc is called to matshal bytes to values.
	UnmarshalFunc func([]byte, interface{}) error
	// FileExtension is the extension of files and should correspond to the byte
	// format written and read by MarshalFunc and UnmarshalFunc.
	FileExtension,

	RootFileName string
}

FileMarshaler knows how to turn FileTargets into real files.

func (FileMarshaler) ReadFile

func (fm FileMarshaler) ReadFile(prefix, filePath string, v interface{}) error

ReadFile reads a file at prefix + t.Path into v.

func (FileMarshaler) WriteFile

func (fm FileMarshaler) WriteFile(prefix string, t WriteTarget) error

WriteFile writes a file based on t.

type FileNode

type FileNode struct {
	NodeBase
}

A FileNode represents a node to be stored in a file.

func (*FileNode) ChildPathName

func (n *FileNode) ChildPathName(child Node, key, val reflect.Value) string

ChildPathName returns an empty string (file targets don't have children).

func (FileNode) Detect

func (FileNode) Detect(base NodeBase) error

Detect always returns nil.

func (FileNode) New

func (FileNode) New(base NodeBase, _ *Codec) (Node, error)

New returns a new file node and nil error.

func (*FileNode) ReadTargets

func (n *FileNode) ReadTargets(c ReadContext, val Val) error

ReadTargets reads a single file target.

func (*FileNode) WriteTargets

func (n *FileNode) WriteTargets(c WriteContext, val Val) error

WriteTargets returns the write target for this file.

type FileReader

type FileReader interface {
	ReadFile(prefix, filePath string, v interface{}) error
}

FileReader reads data from prefix + target.Path() into target.Data.

type FileTarget

type FileTarget struct {
	FilePath string
	Value    interface{}
}

FileTarget represents a target file to be written.

func (FileTarget) Data

func (ft FileTarget) Data() interface{}

Data returns the Value.

func (FileTarget) Path

func (ft FileTarget) Path() string

Path returns FilePath.

type FileTargets

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

FileTargets is a map of file targets.

func MakeFileTargets

func MakeFileTargets(capacity int) FileTargets

MakeFileTargets creates a new FileTargets with a starting capacity.

func MustNewFileTargets

func MustNewFileTargets(targets ...*FileTarget) FileTargets

MustNewFileTargets wraps NewFileTargets and panics if it returns an error.

func NewFileTargets

func NewFileTargets(targets ...*FileTarget) (FileTargets, error)

NewFileTargets creates a new FileTargets.

func (FileTargets) Add

func (fts FileTargets) Add(targets ...*FileTarget) error

Add adds any number of file targets to this one. Returns an error if any of them share a path.

func (FileTargets) AddAll

func (fts FileTargets) AddAll(other FileTargets) error

AddAll adds the contents of another FileTargets to this one. Returns an error if any of them share a path.

func (FileTargets) Len

func (fts FileTargets) Len() int

Len returns the length.

func (FileTargets) Paths

func (fts FileTargets) Paths() []string

Paths returns the paths of all file targets.

func (FileTargets) Snapshot

func (fts FileTargets) Snapshot() map[string]*FileTarget

Snapshot returns the map this FileTargets represents.

type FileTreeReader

type FileTreeReader struct {
	// FileExtension is the extension of files to consider.
	FileExtension string
	// Prefix is the path prefix.
	Prefix string
	// RootFileName is the root file name.
	RootFileName string
}

FileTreeReader gets targets from the filesystem.

func NewFileTreeReader

func NewFileTreeReader(ext, rootFileName string) *FileTreeReader

NewFileTreeReader returns a new FileTreeReader configured to consider files with extension ext.

func (*FileTreeReader) MakeWalkFunc

func (ftr *FileTreeReader) MakeWalkFunc(targets FileTargets) filepath.WalkFunc

MakeWalkFunc makes a func to process a single filesystem object.

func (*FileTreeReader) ReadTree

func (ftr *FileTreeReader) ReadTree(prefix string) (FileTargets, error)

ReadTree reads a tree rooted at prefix and generates a target from each file with extension FileExtension found in the tree.

type FileWriter

type FileWriter interface {
	// WriteFile writes a file representing target, by joining prefix with
	// Target.Path()
	WriteFile(prefix string, target WriteTarget) error
}

FileWriter is something that can write Targets as files.

type JSONTag

type JSONTag struct {
	Ignore, String, OmitEmpty bool
	Name                      string
}

JSONTag represents a json field tag.

func ParseJSONTag

func ParseJSONTag(field reflect.StructField) JSONTag

ParseJSONTag parses a json field tag from a struct field. Only strings, floats, integers, and booleans can be quoted.

type MapNode

type MapNode struct {
	*DirNodeBase
	KeyType reflect.Type
	// MarshalKey gets a string from the key.
	MarshalKey func(key Val) string
	// UnmarshalKey sets a key from a string.
	UnmarshalKey func(key string, val reflect.Value) error
}

A MapNode represents a map node to be stored in a directory.

func (*MapNode) ChildPathName

func (n *MapNode) ChildPathName(child Node, key, val reflect.Value) string

ChildPathName returns the key as a string.

func (MapNode) Detect

func (MapNode) Detect(base NodeBase) error

Detect returns nil if this base is a map.

func (MapNode) New

func (MapNode) New(base NodeBase, c *Codec) (Node, error)

New returns a new MapNode.

func (*MapNode) ReadTargets

func (n *MapNode) ReadTargets(c ReadContext, val Val) error

ReadTargets reads targets into map entries.

func (*MapNode) WriteTargets

func (n *MapNode) WriteTargets(c WriteContext, val Val) error

WriteTargets writes all map elements.

type Node

type Node interface {
	// Detect returns nil if this node can handle this base type.
	Detect(NodeBase) error
	// New returns a new instance of a node.
	New(NodeBase, *Codec) (Node, error)
	// ID returns this node's ID.
	ID() NodeID
	// FixedPathName returns the indubitable path segment name of this node.
	FixedPathName() (string, bool)
	// ChildPathName returns the path segment for children of this node.
	// If the node's parent is a map or slice, both key and val will have
	// valid values, with val having the same type as this node.
	// If the node's parent is a map, then the key will be a value of the
	// parent's key type.
	// If the node's parent is a slice, then key will be an int value
	// representing the index of this element.
	// If the node's parent is a struct, then key will be an invalid value,
	// and val will be the value of that struct field.
	ChildPathName(child Node, key, val reflect.Value) string
	// PathName returns the path name of this node. Implemented in NodeBase.
	PathName(Val) string
	// WriteTargets writes file targets for this node to the context.
	WriteTargets(c WriteContext, val Val) error
	// Write writes file targets for this node to the context by first ensuring
	// val is not a pointer and then calling WriteTargets.
	Write(c WriteContext, val Val) error
	// Read wraps ReadTargets and takes care of pointers.
	Read(c ReadContext, val Val) error
	// ReadTargets reads key from contexts and returns its value.
	ReadTargets(c ReadContext, val Val) error

	NewVal() Val
	NewValFrom(reflect.Value) Val
	NewKeyedVal(key reflect.Value) Val
	NewKeyedValFrom(key, val reflect.Value) Val
}

Node represents a generic node in the structure.

type NodeBase

type NodeBase struct {
	NodeID
	// Parent is the parent of this node. It is nil only for the root node.
	Parent Node
	// FieldInfo is the field info for this node.
	Field *FieldInfo
	// Zero is a zero value of this node's Type.
	Zero interface{}
	// HasKey indicates if this type has a key (e.g. maps and slices)
	HasKey bool
	// Kind is the kind of NodeID.Type.
	Kind reflect.Kind
	// contains filtered or unexported fields
}

NodeBase is a node in an analysis.

func NewNodeBase

func NewNodeBase(id NodeID, parent Node, field *FieldInfo, self *Node) NodeBase

NewNodeBase returns a new NodeBase.

func (NodeBase) FixedPathName

func (base NodeBase) FixedPathName() (string, bool)

FixedPathName returns the fixed path name of this node. If there is no fixed path name, returns empty string and false. Otherwise returns the fixed path name and true.

func (NodeBase) ID

func (base NodeBase) ID() NodeID

ID returns the ID of this node base.

func (NodeBase) NewKeyedVal

func (base NodeBase) NewKeyedVal(key reflect.Value) Val

NewKeyedVal is similar to NewVal but adds an associated key.

func (NodeBase) NewKeyedValFrom

func (base NodeBase) NewKeyedValFrom(k, v reflect.Value) Val

NewKeyedValFrom is similar to NewValFrom but adds an associated key.

func (NodeBase) NewVal

func (base NodeBase) NewVal() Val

NewVal creates a new Val of this node's type.

func (NodeBase) NewValFrom

func (base NodeBase) NewValFrom(v reflect.Value) Val

NewValFrom creates a Val from an existing value.

func (NodeBase) PathName

func (base NodeBase) PathName(val Val) string

PathName returns the path name segment of this node by querying its tag, field name, and parent's ChildPathName func.

func (NodeBase) Read

func (base NodeBase) Read(c ReadContext, val Val) error

func (NodeBase) Write

func (base NodeBase) Write(c WriteContext, val Val) error

type NodeID

type NodeID struct {
	// ParentType is the type of this node's parent.
	ParentType,

	Type reflect.Type
	// IsPtr indicates if OwnType is a pointer really.
	IsPtr bool
	// FieldName is the name of the parent field containing this node. FieldName
	// will be empty unless ParentType is a struct.
	FieldName string
}

NodeID identifies a node in the tree.

func NewNodeID

func NewNodeID(parentType, typ reflect.Type, fieldName string) (NodeID, error)

NewNodeID creates a new node ID.

func (NodeID) String

func (id NodeID) String() string

type NodeSet

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

NodeSet is a set of Node pointers indexed by ID.

func NewNodeSet

func NewNodeSet() NodeSet

NewNodeSet creates a new node set.

func (NodeSet) Register

func (ns NodeSet) Register(id NodeID) (*Node, bool)

Register tries to register a node ID. If the ID is not yet registered, it returns a new node pointer and true. Otherwise it returns the already registered node pointer and false.

type ReadContext

type ReadContext struct {

	// Reader reads data from path.
	Reader FileReader
	// Parent is the parent read context.
	Parent *ReadContext
	// PathName is the name of this section of the path.
	PathName string
	// Prefix is the path prefix.
	Prefix string
	// contains filtered or unexported fields
}

ReadContext is context collected during a read opration.

func NewReadContext

func NewReadContext(prefix string, targets FileTargets, reader FileReader) ReadContext

NewReadContext returns a new read context.

func (ReadContext) Exists

func (c ReadContext) Exists() bool

Exists checks that a file exists at the current path.

func (ReadContext) List

func (c ReadContext) List() []string

List lists files in the current directory. TODO: This is horrible, need a tree file structure for targets.

func (ReadContext) Path

func (c ReadContext) Path() string

Path returns the path of this context.

func (ReadContext) Push

func (c ReadContext) Push(pathName string) ReadContext

Push creates a derivative node context.

func (ReadContext) Read

func (c ReadContext) Read(v interface{}) error

type ReadTarget

type ReadTarget interface {
	// Path is the path where this target is stored.
	Path() string
}

ReadTarget represents an input target, typically a file.

type SliceNode

type SliceNode struct {
	*DirNodeBase
}

A SliceNode represents a slice to be stored in a directory.

func (*SliceNode) ChildPathName

func (n *SliceNode) ChildPathName(child Node, key, val reflect.Value) string

ChildPathName returns the slice index as a string.

func (SliceNode) Detect

func (SliceNode) Detect(base NodeBase) error

Detect returns nil if this base is a slice.

func (SliceNode) New

func (SliceNode) New(base NodeBase, c *Codec) (Node, error)

New returns a new slice node.

func (*SliceNode) ReadTargets

func (n *SliceNode) ReadTargets(c ReadContext, val Val) error

ReadTargets reads targets into slice indicies.

func (*SliceNode) WriteTargets

func (n *SliceNode) WriteTargets(c WriteContext, val Val) error

WriteTargets writes all the elements of the slice.

type SpecialMapNode

type SpecialMapNode struct {
	NodeBase
	Map    *MapNode
	GetAll func(Val) (reflect.Value, error)
	SetAll func(on Val, to reflect.Value) error
}

SpecialMapNode represents a struct node with GetAll and SetAll methods.

func (*SpecialMapNode) ChildPathName

func (n *SpecialMapNode) ChildPathName(child Node, key, val reflect.Value) string

ChildPathName delegates to MapNode.

func (SpecialMapNode) Detect

func (SpecialMapNode) Detect(base NodeBase) error

Detect returns nil if base is a struct with appropriate GetAll and SetAll methods.

func (SpecialMapNode) New

func (SpecialMapNode) New(base NodeBase, c *Codec) (Node, error)

New returns a new SpecialMapNode.

func (*SpecialMapNode) ReadTargets

func (n *SpecialMapNode) ReadTargets(c ReadContext, val Val) error

ReadTargets delegates to MapNode.

func (*SpecialMapNode) WriteTargets

func (n *SpecialMapNode) WriteTargets(c WriteContext, val Val) error

WriteTargets delegates to MapNode.

type StructNode

type StructNode struct {
	FileNode
	// Fields is a map of simple struct field names to their types.
	Fields map[string]reflect.Type
	// Children is a map of field named to node pointers.
	Children map[string]*Node
}

StructNode represents a struct to be stored in a file.

func (*StructNode) ChildPathName

func (n *StructNode) ChildPathName(child Node, key, val reflect.Value) string

ChildPathName returns the path segment for this node's children.

func (StructNode) Detect

func (StructNode) Detect(base NodeBase) error

Detect returns nil if this base is a struct.

func (StructNode) New

func (StructNode) New(base NodeBase, c *Codec) (Node, error)

New creates a new StructNode.

func (*StructNode) ReadTargets

func (n *StructNode) ReadTargets(c ReadContext, val Val) error

ReadTargets reads targets into struct fields.

func (*StructNode) WriteTargets

func (n *StructNode) WriteTargets(c WriteContext, val Val) error

WriteTargets generates file targets.

type Tag

type Tag struct {
	None,
	Ignore,
	IsDir bool
	PathName,
	Key,
	SetKey string
}

Tag contains a parsed struct field tag.

type Val

type Val struct {
	Base *NodeBase
	// Ptr is the underlying pointer value.
	Ptr reflect.Value
	// Key is the associated key for this value. May be invalid.
	Key reflect.Value
	// IsPtr indicates whether the final version of this value should be a
	// pointer.
	IsPtr bool
}

Val wraps a reflect.Value so other code does not need to be aware of pointer wrapping and unwrapping.

func NewFreeValFrom

func NewFreeValFrom(v reflect.Value) Val

NewFreeValFrom creates a new free value (not attached to any node).

func (Val) Append

func (v Val) Append(elem Val)

Append appends a val to this slice. It panics if v is not a slice.

func (Val) Final

func (v Val) Final() reflect.Value

Final returns the final reflect.Value. Note that this will never be nil.

func (Val) FinalInterface

func (v Val) FinalInterface() interface{}

FinalInterface returns the true final value as an interface{}.

func (Val) GetField

func (v Val) GetField(name string) reflect.Value

GetField gets a field value by name. It panics if this value is not a struct.

func (Val) Interface

func (v Val) Interface(filter func(interface{}) bool) (interface{}, bool)

Interface selects the pointer or non-pointer version of this val that satisfies the filter function. It returns nil, false if none pass the filter.

func (Val) IsZero

func (v Val) IsZero() bool

IsZero means "is zero or nil or invalid".

func (Val) MapElements

func (v Val) MapElements(elemNode Node) []Val

MapElements returns a slice of Val representing key, value pairs from this map. It panics if v does not represent a map.

func (Val) Method

func (v Val) Method(name string) reflect.Value

Method wraps MethodByName.

func (Val) SetField

func (v Val) SetField(name string, val Val)

SetField sets a field on this struct value. It panics if this value is not a struct.

func (Val) SetMapElement

func (v Val) SetMapElement(val Val)

SetMapElement sets a map element using key and value from val. It panics if this value is not a map with corresponding key and value types.

func (Val) ShouldWrite

func (v Val) ShouldWrite() bool

ShouldWrite returns true if this value is not zero or if it does have a key. Zero unkeyed values are never written.

func (Val) SliceElements

func (v Val) SliceElements(elemNode Node) []Val

SliceElements returns a slice of Vals representing the index, value pairs from this slice. It panics if v is not a slice.

type WriteContext

type WriteContext struct {

	// Parent is the parent write context.
	Parent *WriteContext
	// PathName is the name of this section of the path.
	PathName string
	// contains filtered or unexported fields
}

WriteContext is context collected during a write opration.

func NewWriteContext

func NewWriteContext() WriteContext

NewWriteContext returns a new write context.

func (WriteContext) Path

func (c WriteContext) Path() string

Path returns the path of this context.

func (WriteContext) Push

func (c WriteContext) Push(pathName string) WriteContext

Push creates a derivative node context.

func (WriteContext) SetRawValue

func (c WriteContext) SetRawValue(v interface{}) error

SetRawValue sets the raw value of the current path.

func (WriteContext) SetValue

func (c WriteContext) SetValue(val Val) error

SetValue sets the value of the current path.

type WriteTarget

type WriteTarget interface {
	// Path is the path where this target is stored.
	Path() string
	// Data is the go value to be stored.
	Data() interface{}
}

WriteTarget represents an output target, typically a file.

Jump to

Keyboard shortcuts

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