156 lines
5.1 KiB
Go
156 lines
5.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"strings"
|
|
)
|
|
|
|
func init() {
|
|
gob.Register(ContainerMethod{})
|
|
gob.Register(AsserterMethod{})
|
|
gob.Register(GetterMethod{})
|
|
gob.Register(SetterMethod{})
|
|
gob.Register(IOMethod{})
|
|
}
|
|
|
|
type Interface struct {
|
|
Comment Comment
|
|
Name string
|
|
Embeds []EmbeddedInterface
|
|
Methods []Method // actual methods
|
|
}
|
|
|
|
type EmbeddedInterface struct {
|
|
Comment Comment
|
|
InterfaceName string
|
|
}
|
|
|
|
// IsContainer returns true if the interface is a frontend container interface,
|
|
// that is when its name has "Container" at the end.
|
|
func (i Interface) IsContainer() bool {
|
|
return strings.HasSuffix(i.Name, "Container")
|
|
}
|
|
|
|
type Method interface {
|
|
UnderlyingName() string
|
|
UnderlyingComment() Comment
|
|
internalMethod()
|
|
}
|
|
|
|
type method struct {
|
|
Comment Comment
|
|
Name string
|
|
}
|
|
|
|
func (m method) UnderlyingName() string { return m.Name }
|
|
func (m method) UnderlyingComment() Comment { return m.Comment }
|
|
func (m method) internalMethod() {}
|
|
|
|
// GetterMethod is a method that returns a regular value. These methods must not
|
|
// do any IO. An example of one would be ID() returning ID.
|
|
type GetterMethod struct {
|
|
method
|
|
|
|
// Parameters is the list of parameters in the function.
|
|
Parameters []NamedType
|
|
// Returns is the list of named types returned from the function.
|
|
Returns []NamedType
|
|
// ErrorType is non-empty if the function returns an error at the end of
|
|
// returns. For the most part, this field should be "error" if that is the
|
|
// case, but some methods may choose to extend the error base type.
|
|
ErrorType string
|
|
}
|
|
|
|
// ReturnError returns true if the method can error out.
|
|
func (m GetterMethod) ReturnError() bool {
|
|
return m.ErrorType != ""
|
|
}
|
|
|
|
// SetterMethod is a method that sets values. These methods must not do IO, and
|
|
// they have to be non-blocking. They're used only for containers. Actual setter
|
|
// methods implemented by the backend belongs to IOMethods.
|
|
//
|
|
// Clients should always keep track of the values given to setters and free them
|
|
// once the setters are called again with new values.
|
|
type SetterMethod struct {
|
|
method
|
|
|
|
// Parameters is the list of parameters in the function. These parameters
|
|
// should be the parameters to set.
|
|
Parameters []NamedType
|
|
// ErrorType is non-empty if the function returns an error at the end of
|
|
// returns. An error may be returned from the backend if the input is
|
|
// invalid, but it must not do IO. Frontend setters must never error.
|
|
ErrorType string
|
|
}
|
|
|
|
// IOMethod is a regular method that can do IO and thus is blocking. These
|
|
// methods usually always return errors. IOMethods must always have means of
|
|
// cancelling them in the API, but implementations don't have to use it; as
|
|
// such, the user should always have a timeout to gracefully wait.
|
|
type IOMethod struct {
|
|
method
|
|
|
|
// Parameters is the list of parameters in the function.
|
|
Parameters []NamedType
|
|
// ReturnValue is the return value in the function.
|
|
ReturnValue NamedType
|
|
// ErrorType is non-empty if the function returns an error at the end of
|
|
// returns. For the most part, this field should be "error" if that is the
|
|
// case, but some methods may choose to extend the error base type.
|
|
ErrorType string
|
|
// Disposer indicates that this method signals the disposal of the interface
|
|
// that implements it. This is used similarly to stop functions, except all
|
|
// disposer functions can be synchronous, and the frontend should handle
|
|
// indicating such. The frontend can also ignore the result and run the
|
|
// method in a dangling goroutine, but it must gracefully wait for it to be
|
|
// done on exit.
|
|
//
|
|
// Similarly to the stop function, the instance that the disposer method belongs
|
|
// to will also be considered invalid and should be freed once the function
|
|
// returns regardless of the error.
|
|
Disposer bool
|
|
}
|
|
|
|
// ReturnError returns true if the method can error out.
|
|
func (m IOMethod) ReturnError() bool {
|
|
return m.ErrorType != ""
|
|
}
|
|
|
|
// ContainerMethod is a method that uses a Container. These methods can do IO,
|
|
// and they must always take in a context and return an error. The context is
|
|
// used for both stopping an ongoing IO operation and disconnecting background
|
|
// handlers for the container.
|
|
type ContainerMethod struct {
|
|
method
|
|
|
|
// ContainerType is the name of the container interface. The name will
|
|
// almost always have "Container" as its suffix.
|
|
ContainerType string
|
|
}
|
|
|
|
// Qual returns what TypeQual returns with m.ContainerType.
|
|
func (m ContainerMethod) Qual() (path, name string) {
|
|
return TypeQual(m.ContainerType)
|
|
}
|
|
|
|
// AsserterMethod is a method that allows the parent interface to extend itself
|
|
// into children interfaces. These methods must not do IO.
|
|
type AsserterMethod struct {
|
|
// ChildType is the children type that is returned.
|
|
ChildType string
|
|
}
|
|
|
|
func (m AsserterMethod) internalMethod() {}
|
|
func (m AsserterMethod) UnderlyingComment() Comment { return Comment{} }
|
|
|
|
// UnderlyingName returns the name of the method.
|
|
func (m AsserterMethod) UnderlyingName() string {
|
|
return "As" + m.ChildType
|
|
}
|
|
|
|
// Qual returns what TypeQual returns with m.ChildType.
|
|
func (m AsserterMethod) Qual() (path, name string) {
|
|
return TypeQual(m.ChildType)
|
|
}
|