Documentation ¶
Overview ¶
Package olrgen is a code generation framework for operations log encoding.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ReturnError ¶ added in v0.1.0
ReturnError returns a handler to simplify building error messages with structured context in a way that closely replicates the API of github.com/sirkon/errors error processing package.
Example usage:
olrgen.ReturnError().Wrap("err", "$decode").Int("count-$0", 14).Rend(r, countIndex)
The code rendered will look like – countIndex, say, is equal to 25:
return errors.Wrap(err, "decode BranchName.argName(argType)").Int("count-25", 14)
There is a set of predefined values in the code rendering context, besides $decode. Here is the full list (2023-05-15):
- $decode -> "decode $branch.$dst($dstType)"
- $recordTooSmall -> "record buffer is too small"
- $malformedUvarint -> "malformed uvarint sequence"
- $malformedVarint -> "malformed varint sequence"
func Run ¶
func Run( appName string, hnlrs *TypesHandlers, ) error
Run is the entry point of a final utility.
func SetStructuredErrorsPkgPath ¶ added in v0.3.0
func SetStructuredErrorsPkgPath(p string)
SetStructuredErrorsPkgPath sets custom errors package.
Types ¶
type CustomTypeHandler ¶
type CustomTypeHandler func(handlerPlaceholder, *TypesHandlers) error
CustomTypeHandler custom option type. Cannot be defined outside of this package and only implemented by TypeHandlerByName and NewTypeHandler functions.
func NewTypeHandler ¶
func NewTypeHandler(handler func(p types.Type) TypeHandler) CustomTypeHandler
NewTypeHandler adds custom handler.
func TypeHandlerByName ¶
func TypeHandlerByName(name string, handler func() TypeHandler) CustomTypeHandler
TypeHandlerByName adds this custom handler for the given type.
type L ¶ added in v0.1.0
L does the opposite job to Q for structured values: When you want the builder key to be shown as a variable you use olrgen.L:
olrgen.ReturnError()...Str(olrgen.L("key"), olrgen.Q("value"))...
This will be rendered as
return errors...Str(key, "value")
type LoggerType ¶
LoggerType error logging abstraction to log with text position.
func Logger ¶
func Logger(fset *token.FileSet) LoggerType
Logger returns a standard LoggerType implementation that seems to be sufficient for most needs.
type Q ¶ added in v0.1.0
Q is to be used for structured values to be string. Like
orlgen.ReturnError()...Str("key", olrgen.Q("value"))...
To be rendered like
return errors...Str("key", "value")
It will be
return errors...Str("key", value)
Without olrgen.Q
type TypeHandler ¶
type TypeHandler interface { // Name returns a Go type name this handler is for. Meaning // it will be int8 for int8 handler, etc. Name(r *Go) string // Pre renders can be used to render additional stuff at the top // of the encoding function. // Take a look at the example: // // Let we have a recorder interface // // type LogRecorder interface{ // … // Append(sid types.Index, data []byte) error // … // } // // This means Append method for an implementation of LogRecorder // must be generated. And it looks like // // func (x *LogRecorderImpl) Append(sid types.Index, data []byte) error { // {% code generated by Pre calls by handlers of each argument's type %} // … // } // // A handler can put everything it wants in that area, including // local variables, additional checks, whatever. // // It can be used to store computed lengths for []byte and string // types handlers for instance. Kinda meaningless for them as // it len(x) is fast to compute, but some types can be tougher to // deal with, so this can be pretty useful for them. Pre(r *Go, src string) // Len returns a length of buffer required to keep an encoded value. // It is not possible to have a meaningful value for every type. // In particular, []byte and string required buffer lentghs are // only known at the runtime. Implementation MUST return a negative // value in this case. Len() int // LenExpr gives an expression to compute required buffer length // to encode a type being handled. Must be be equal to // strconv.Itoa(x.Len()) // In case of fixed length, and it is checked. LenExpr(r *Go, src string) string // Encoding generates a code that encodes a value of $src into $dst. // $src and $dst values are also available in the scope of r under // these exact names, i.e. you can reference them like this: // // $dst = binary.LittleEndian.AppendUint32($dst, $src) // // And there's $dstType scope variable too containing $dst type. // The $dst slice is guaranteed to have enough capacity to store // all encoded data, and it always comes empty, so every encoding // must follow Append "protocol". // // A code is rendered within a context where it (a code generated) // may return an error. An example of how the end result will look // like: // // func (x *LogRecorderImpl) Append(sid types.Index, data []byte) error { // dataLen := varsize.Len(data) + len(data) // // dst := x.allocateBuffer(4 + 16 + dataLen) // returns empty slice with enough capacity // // // Autogenerated data to put Append method code. // dst = binary.LittleEndian.AppendUint32(dst, uint32(logRecorderCodeAppend)) // // // Autogenerated code to encode Index type of the sid parameter. // dst = dst[:len(dst)+16] // types.IndexEncode(dst, sid) // // // Autogenerated code to encode []byte type of the data parameter. // dst = binary.AppendUvarint(dst, uint64(len(data))) // dst = append(dst, data...) // // if _, err := x.writeBuffer(dst); err != nil { // return errors.Wrap(err, "write encoded data") // Forcing my errors pkg LMAO. // } // // return nil // } // // It is guaranteed err name is not taken by anything generated - err // parameter name is prohibited and reserved for its common usage. // It is not guaranteed 100% though because a user can slap // something like // err := "Hello World!" // in his custom encoding code. // Take a look at [Auto] handler to see how to deal with err // within an encoding function scope. // // [Auto]: ./internal/handlers/handler_auto.go Encoding(r *Go, dst, src string) // Decoding generates a code that decodes a data from $src and stores // it into $dst. // - The semantics is exactly the same as for the Encoding, except // it is $src that is []byte now and $dst is a variable of a // respective type. // - It is $srcType instead of the $dstType this time for obvious // reasons. // - Same single return value – an error – context for a generated // code. // // Another sort of compliance is needed in this case though: // - We encode reading data at the head of the $src. // - When encoding ends we cut amount of bytes we read from the $dst // to encode. We will cut 4 bytes for encoded int32 value for example. // - Ulike the Encoding() we may return true or false, in case if we cut // the head ourselves or want the autogen to make this for us. // The general advice is to cut manually for a variable length encoding // and let the autogen do this for the fixed sized ones. // // And here is the context similar to one a code generated will work within: // // type LogRecorder interface{ // Append(sid Index, data []byte) error // Delete(sid Index) error // } // … // // func DispatchLog(h LogHandler, rec []byte) error { // if len(data) < 4 { // return errors.New("extract branch code: record buffer is too small") // } // // switch v := logRecorderCode(binary.LittleEndian.Uint32(rec)); v { // case logRecorderCodeAppend: // if err := dispatchLogDecodeAppend(h, rec[4:]); err != nil { // return errors.Wrap(err, "dispatch Append branch") // } // case logRecorderCodeDelete: // if err := dispatchLogDecodeDelete(h, rec[4:]); err != nil { // return errors.Wrap(err, "dispatch Delete branch") // } // default: // return errors.Newf("unknown branch code %d", v) // } // } // // func dispatchLogDecodeAppend(h LogHandler, rec []byte) error { // // decoding code here spawning sid and data variables // // var sid Index // // sid decoding in here // ... // if err := h.Append(sid, data); err != nil { // return errors.New("call Append operation handler").Stg("sid", sid).Int("data-len", len(data)) // } // // return nil // } // // Decoding method body has the same err guarantees as for the Encoding, // that is err is not taken by anything generated by this library handlers. // Remember, $dst is always declared as // var $dst $dstType // Before the code produced by a Decoding call, you just use this variable. Decoding(r *Go, dst, src string) bool }
TypeHandler an abstraction for a codegen support of a type.
type TypesHandlers ¶
type TypesHandlers struct {
// contains filtered or unexported fields
}
TypesHandlers this returns type handlers.
func NewTypesHandlers ¶
func NewTypesHandlers(handlers ...CustomTypeHandler) (*TypesHandlers, error)
NewTypesHandlers constructor. User can additional handlers via TypeHandlerByName and NewTypeHandler.
func (*TypesHandlers) Handler ¶
func (h *TypesHandlers) Handler(arg *types.Var) TypeHandler
Handler returns a handler for the given type by its name.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
internal/example
Package example.
|
Package example. |
internal
|
|
er
Package er provides helpers to simplify building errors returning.
|
Package er provides helpers to simplify building errors returning. |
generator
Package generator makes code generation.
|
Package generator makes code generation. |
handlers
Package handlers for builtin types.
|
Package handlers for builtin types. |
logger
Package logger provides loggers for testing and for the actual job.
|
Package logger provides loggers for testing and for the actual job. |
renderer
Package renderer provides a renderer with a custom reporter.
|
Package renderer provides a renderer with a custom reporter. |
tdetect
Package tdetect provides types detections means.
|
Package tdetect provides types detections means. |
tnmatchers
Package tnmatchers means Type Name MATCHERS.
|
Package tnmatchers means Type Name MATCHERS. |