Implement JSONLoad, To, and On functions for ForgeFed types
parent
6a6c6b3481
commit
27cda2fcd4
2
go.mod
2
go.mod
|
@ -299,7 +299,7 @@ replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142
|
|||
|
||||
replace github.com/satori/go.uuid v1.2.0 => github.com/gofrs/uuid v4.2.0+incompatible
|
||||
|
||||
replace github.com/go-ap/activitypub => gitea.com/Ta180m/activitypub v0.0.0-20220711172827-b05423b54985
|
||||
replace github.com/go-ap/activitypub => gitea.com/Ta180m/activitypub v0.0.0-20220821033718-79a43a998240
|
||||
|
||||
exclude github.com/gofrs/uuid v3.2.0+incompatible
|
||||
|
||||
|
|
4
go.sum
4
go.sum
|
@ -73,8 +73,8 @@ contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcig
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||
gitea.com/Ta180m/activitypub v0.0.0-20220711172827-b05423b54985 h1:mFjFQxAsUdcvtM3klWtTbkhGnsRVF+DPhZPofsKmPlk=
|
||||
gitea.com/Ta180m/activitypub v0.0.0-20220711172827-b05423b54985/go.mod h1:KDY/LAOthmTlRA4ft9TKrvPKVe+AZaSaU+3HS/UITvU=
|
||||
gitea.com/Ta180m/activitypub v0.0.0-20220821033718-79a43a998240 h1:ZW+5jY1ibiRPGoBlUcwBA9eHdFVGD70qWrKXw877Yd4=
|
||||
gitea.com/Ta180m/activitypub v0.0.0-20220821033718-79a43a998240/go.mod h1:Md4CYDr9vFkojPjSqzG04PN03hgnd+X3jf4i8Nbb7OE=
|
||||
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb h1:Yy0Bxzc8R2wxiwXoG/rECGplJUSpXqCsog9PuJFgiHs=
|
||||
gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
|
||||
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
|
||||
|
|
|
@ -27,6 +27,7 @@ func AuthorizeInteraction(ctx *context.Context) {
|
|||
}
|
||||
|
||||
ap.ItemTyperFunc = forgefed.GetItemByType
|
||||
ap.JSONItemUnmarshal = forgefed.JSONUnmarshalerFn
|
||||
object, err := ap.UnmarshalJSON(resp)
|
||||
if err != nil {
|
||||
ctx.ServerError("UnmarshalJSON", err)
|
||||
|
@ -51,11 +52,19 @@ func AuthorizeInteraction(ctx *context.Context) {
|
|||
}
|
||||
ctx.Redirect(name)
|
||||
case forgefed.RepositoryType:
|
||||
err = FederatedRepoNew(ctx, object.(forgefed.Repository))
|
||||
err = forgefed.OnRepository(object, func(r *forgefed.Repository) error {
|
||||
return FederatedRepoNew(ctx, r)
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("FederatedRepoNew", err)
|
||||
return
|
||||
}
|
||||
username, reponame, err := repositoryIRIToName(object.GetLink())
|
||||
if err != nil {
|
||||
ctx.ServerError("repositoryIRIToName", err)
|
||||
return
|
||||
}
|
||||
ctx.Redirect(username+"/"+reponame)
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusOK)
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
"code.gitea.io/gitea/modules/forgefed"
|
||||
)
|
||||
|
||||
// Create a new federated repo from a Repository object
|
||||
func FederatedRepoNew(ctx context.Context, repository forgefed.Repository) error {
|
||||
func FederatedRepoNew(ctx context.Context, repository *forgefed.Repository) error {
|
||||
ownerIRI, err := repositoryIRIToOwnerIRI(repository.GetLink())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -23,9 +23,14 @@ func FederatedRepoNew(ctx context.Context, repository forgefed.Repository) error
|
|||
return err
|
||||
}
|
||||
|
||||
repo := repo_model.Repository{
|
||||
// TODO: Check if repo already exists
|
||||
repo, err := repo_service.CreateRepository(user, user, models.CreateRepoOptions{
|
||||
Name: repository.Name.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if repository.ForkedFrom != nil {
|
||||
repo.IsFork = true
|
||||
forkedFrom, err := repositoryIRIToRepository(ctx, repository.ForkedFrom.GetLink())
|
||||
|
@ -34,7 +39,5 @@ func FederatedRepoNew(ctx context.Context, repository forgefed.Repository) error
|
|||
}
|
||||
repo.ForkID = forkedFrom.ID
|
||||
}
|
||||
|
||||
// TODO: Check if repo already exists
|
||||
return models.CreateRepository(ctx, user, user, &repo, false)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
package forgefed
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
ap "github.com/go-ap/activitypub"
|
||||
"github.com/valyala/fastjson"
|
||||
)
|
||||
|
@ -26,30 +29,68 @@ func BranchNew() *Branch {
|
|||
return &o
|
||||
}
|
||||
|
||||
func (br Branch) MarshalJSON() ([]byte, error) {
|
||||
b, err := br.Object.MarshalJSON()
|
||||
if len(b) == 0 || err != nil {
|
||||
func (b Branch) MarshalJSON() ([]byte, error) {
|
||||
bin, err := b.Object.MarshalJSON()
|
||||
if len(bin) == 0 || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b = b[:len(b)-1]
|
||||
if br.Ref != nil {
|
||||
ap.WriteItemJSONProp(&b, "ref", br.Ref)
|
||||
bin = bin[:len(bin)-1]
|
||||
if b.Ref != nil {
|
||||
ap.JSONWriteItemJSONProp(&bin, "ref", b.Ref)
|
||||
}
|
||||
ap.Write(&b, '}')
|
||||
return b, nil
|
||||
ap.JSONWrite(&bin, '}')
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
func (br *Branch) UnmarshalJSON(data []byte) error {
|
||||
func JSONLoadBranch(val *fastjson.Value, b *Branch) error {
|
||||
ap.OnObject(&b.Object, func(o *ap.Object) error {
|
||||
return ap.JSONLoadObject(val, o)
|
||||
})
|
||||
b.Ref = ap.JSONGetItem(val, "ref")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Branch) UnmarshalJSON(data []byte) error {
|
||||
p := fastjson.Parser{}
|
||||
val, err := p.ParseBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
br.Ref = ap.JSONGetItem(val, "ref")
|
||||
|
||||
return ap.OnObject(&br.Object, func(a *ap.Object) error {
|
||||
return ap.LoadObject(val, a)
|
||||
})
|
||||
return JSONLoadBranch(val, b)
|
||||
}
|
||||
|
||||
// ToBranch tries to convert the it Item to a Branch object.
|
||||
func ToBranch(it ap.Item) (*Branch, error) {
|
||||
switch i := it.(type) {
|
||||
case *Branch:
|
||||
return i, nil
|
||||
case Branch:
|
||||
return &i, nil
|
||||
case *ap.Object:
|
||||
return (*Branch)(unsafe.Pointer(i)), nil
|
||||
case ap.Object:
|
||||
return (*Branch)(unsafe.Pointer(&i)), nil
|
||||
default:
|
||||
// NOTE(marius): this is an ugly way of dealing with the interface conversion error: types from different scopes
|
||||
typ := reflect.TypeOf(new(Branch))
|
||||
if i, ok := reflect.ValueOf(it).Convert(typ).Interface().(*Branch); ok {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
return nil, ap.ErrorInvalidType[ap.Object](it)
|
||||
}
|
||||
|
||||
type withBranchFn func(*Branch) error
|
||||
|
||||
// OnBranch calls function fn on it Item if it can be asserted to type *Branch
|
||||
func OnBranch(it ap.Item, fn withBranchFn) error {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
ob, err := ToBranch(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fn(ob)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
package forgefed
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
ap "github.com/go-ap/activitypub"
|
||||
"github.com/valyala/fastjson"
|
||||
|
@ -38,26 +40,64 @@ func (c Commit) MarshalJSON() ([]byte, error) {
|
|||
|
||||
b = b[:len(b)-1]
|
||||
if !c.Created.IsZero() {
|
||||
ap.WriteTimeJSONProp(&b, "created", c.Created)
|
||||
ap.JSONWriteTimeJSONProp(&b, "created", c.Created)
|
||||
}
|
||||
if !c.Committed.IsZero() {
|
||||
ap.WriteTimeJSONProp(&b, "committed", c.Committed)
|
||||
ap.JSONWriteTimeJSONProp(&b, "committed", c.Committed)
|
||||
}
|
||||
ap.Write(&b, '}')
|
||||
ap.JSONWrite(&b, '}')
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func JSONLoadCommit(val *fastjson.Value, c *Commit) error {
|
||||
ap.OnObject(&c.Object, func(o *ap.Object) error {
|
||||
return ap.JSONLoadObject(val, o)
|
||||
})
|
||||
c.Created = ap.JSONGetTime(val, "created")
|
||||
c.Committed = ap.JSONGetTime(val, "committed")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commit) UnmarshalJSON(data []byte) error {
|
||||
p := fastjson.Parser{}
|
||||
val, err := p.ParseBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Created = ap.JSONGetTime(val, "created")
|
||||
c.Committed = ap.JSONGetTime(val, "committed")
|
||||
|
||||
return ap.OnObject(&c.Object, func(a *ap.Object) error {
|
||||
return ap.LoadObject(val, a)
|
||||
})
|
||||
return JSONLoadCommit(val, c)
|
||||
}
|
||||
|
||||
// ToCommit tries to convert the it Item to a Commit object.
|
||||
func ToCommit(it ap.Item) (*Commit, error) {
|
||||
switch i := it.(type) {
|
||||
case *Commit:
|
||||
return i, nil
|
||||
case Commit:
|
||||
return &i, nil
|
||||
case *ap.Object:
|
||||
return (*Commit)(unsafe.Pointer(i)), nil
|
||||
case ap.Object:
|
||||
return (*Commit)(unsafe.Pointer(&i)), nil
|
||||
default:
|
||||
// NOTE(marius): this is an ugly way of dealing with the interface conversion error: types from different scopes
|
||||
typ := reflect.TypeOf(new(Commit))
|
||||
if i, ok := reflect.ValueOf(it).Convert(typ).Interface().(*Commit); ok {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
return nil, ap.ErrorInvalidType[ap.Object](it)
|
||||
}
|
||||
|
||||
type withCommitFn func(*Commit) error
|
||||
|
||||
// OnCommit calls function fn on it Item if it can be asserted to type *Commit
|
||||
func OnCommit(it ap.Item, fn withCommitFn) error {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
ob, err := ToCommit(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fn(ob)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package forgefed
|
|||
|
||||
import (
|
||||
ap "github.com/go-ap/activitypub"
|
||||
"github.com/valyala/fastjson"
|
||||
)
|
||||
|
||||
const ForgeFedNamespaceURI = "https://forgefed.org/ns"
|
||||
|
@ -27,3 +28,31 @@ func GetItemByType(typ ap.ActivityVocabularyType) (ap.Item, error) {
|
|||
}
|
||||
return ap.GetItemByType(typ)
|
||||
}
|
||||
|
||||
// JSONUnmarshalerFn is the type of the function that will load the data from a fastjson.Value into an Item
|
||||
// that the go-ap/activitypub package doesn't know about.
|
||||
func JSONUnmarshalerFn(typ ap.ActivityVocabularyType, val *fastjson.Value, i ap.Item) error {
|
||||
switch typ {
|
||||
case CommitType:
|
||||
return OnCommit(i, func(c *Commit) error {
|
||||
return JSONLoadCommit(val, c)
|
||||
})
|
||||
case BranchType:
|
||||
return OnBranch(i, func(b *Branch) error {
|
||||
return JSONLoadBranch(val, b)
|
||||
})
|
||||
case RepositoryType:
|
||||
return OnRepository(i, func(r *Repository) error {
|
||||
return JSONLoadRepository(val, r)
|
||||
})
|
||||
case PushType:
|
||||
return OnPush(i, func(p *Push) error {
|
||||
return JSONLoadPush(val, p)
|
||||
})
|
||||
case TicketType:
|
||||
return OnTicket(i, func(t *Ticket) error {
|
||||
return JSONLoadTicket(val, t)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
package forgefed
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
ap "github.com/go-ap/activitypub"
|
||||
"github.com/valyala/fastjson"
|
||||
)
|
||||
|
@ -38,30 +41,68 @@ func (p Push) MarshalJSON() ([]byte, error) {
|
|||
|
||||
b = b[:len(b)-1]
|
||||
if p.Target != nil {
|
||||
ap.WriteItemJSONProp(&b, "target", p.Target)
|
||||
ap.JSONWriteItemJSONProp(&b, "target", p.Target)
|
||||
}
|
||||
if p.HashBefore != nil {
|
||||
ap.WriteItemJSONProp(&b, "hashBefore", p.HashBefore)
|
||||
ap.JSONWriteItemJSONProp(&b, "hashBefore", p.HashBefore)
|
||||
}
|
||||
if p.HashAfter != nil {
|
||||
ap.WriteItemJSONProp(&b, "hashAfter", p.HashAfter)
|
||||
ap.JSONWriteItemJSONProp(&b, "hashAfter", p.HashAfter)
|
||||
}
|
||||
ap.Write(&b, '}')
|
||||
ap.JSONWrite(&b, '}')
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (p *Push) UnmarshalJSON(data []byte) error {
|
||||
ps := fastjson.Parser{}
|
||||
val, err := ps.ParseBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func JSONLoadPush(val *fastjson.Value, p *Push) error {
|
||||
ap.OnObject(&p.Object, func(o *ap.Object) error {
|
||||
return ap.JSONLoadObject(val, o)
|
||||
})
|
||||
p.Target = ap.JSONGetItem(val, "target")
|
||||
p.HashBefore = ap.JSONGetItem(val, "hashBefore")
|
||||
p.HashAfter = ap.JSONGetItem(val, "hashAfter")
|
||||
|
||||
return ap.OnObject(&p.Object, func(a *ap.Object) error {
|
||||
return ap.LoadObject(val, a)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Push) UnmarshalJSON(data []byte) error {
|
||||
par := fastjson.Parser{}
|
||||
val, err := par.ParseBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return JSONLoadPush(val, p)
|
||||
}
|
||||
|
||||
// ToPush tries to convert the it Item to a Push object.
|
||||
func ToPush(it ap.Item) (*Push, error) {
|
||||
switch i := it.(type) {
|
||||
case *Push:
|
||||
return i, nil
|
||||
case Push:
|
||||
return &i, nil
|
||||
case *ap.Object:
|
||||
return (*Push)(unsafe.Pointer(i)), nil
|
||||
case ap.Object:
|
||||
return (*Push)(unsafe.Pointer(&i)), nil
|
||||
default:
|
||||
// NOTE(marius): this is an ugly way of dealing with the interface conversion error: types from different scopes
|
||||
typ := reflect.TypeOf(new(Push))
|
||||
if i, ok := reflect.ValueOf(it).Convert(typ).Interface().(*Push); ok {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
return nil, ap.ErrorInvalidType[ap.Object](it)
|
||||
}
|
||||
|
||||
type withPushFn func(*Push) error
|
||||
|
||||
// OnPush calls function fn on it Item if it can be asserted to type *Push
|
||||
func OnPush(it ap.Item, fn withPushFn) error {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
ob, err := ToPush(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fn(ob)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
package forgefed
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
ap "github.com/go-ap/activitypub"
|
||||
"github.com/valyala/fastjson"
|
||||
)
|
||||
|
@ -39,30 +42,68 @@ func (r Repository) MarshalJSON() ([]byte, error) {
|
|||
|
||||
b = b[:len(b)-1]
|
||||
if r.Team != nil {
|
||||
ap.WriteItemJSONProp(&b, "team", r.Team)
|
||||
ap.JSONWriteItemJSONProp(&b, "team", r.Team)
|
||||
}
|
||||
if r.Forks != nil {
|
||||
ap.WriteItemJSONProp(&b, "forks", r.Forks)
|
||||
ap.JSONWriteItemJSONProp(&b, "forks", r.Forks)
|
||||
}
|
||||
if r.ForkedFrom != nil {
|
||||
ap.WriteItemJSONProp(&b, "forkedFrom", r.ForkedFrom)
|
||||
ap.JSONWriteItemJSONProp(&b, "forkedFrom", r.ForkedFrom)
|
||||
}
|
||||
ap.Write(&b, '}')
|
||||
ap.JSONWrite(&b, '}')
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func JSONLoadRepository(val *fastjson.Value, r *Repository) error {
|
||||
ap.OnActor(&r.Actor, func(a *ap.Actor) error {
|
||||
return ap.JSONLoadActor(val, a)
|
||||
})
|
||||
r.Team = ap.JSONGetItem(val, "team")
|
||||
r.Forks = ap.JSONGetItem(val, "forks")
|
||||
r.ForkedFrom = ap.JSONGetItem(val, "forkedFrom")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) UnmarshalJSON(data []byte) error {
|
||||
p := fastjson.Parser{}
|
||||
val, err := p.ParseBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Team = ap.JSONGetItem(val, "team")
|
||||
r.Forks = ap.JSONGetItem(val, "forks")
|
||||
r.ForkedFrom = ap.JSONGetItem(val, "forkedFrom")
|
||||
|
||||
return ap.OnActor(&r.Actor, func(a *ap.Actor) error {
|
||||
return ap.LoadActor(val, a)
|
||||
})
|
||||
return JSONLoadRepository(val, r)
|
||||
}
|
||||
|
||||
// ToRepository tries to convert the it Item to a Repository Actor.
|
||||
func ToRepository(it ap.Item) (*Repository, error) {
|
||||
switch i := it.(type) {
|
||||
case *Repository:
|
||||
return i, nil
|
||||
case Repository:
|
||||
return &i, nil
|
||||
case *ap.Actor:
|
||||
return (*Repository)(unsafe.Pointer(i)), nil
|
||||
case ap.Actor:
|
||||
return (*Repository)(unsafe.Pointer(&i)), nil
|
||||
default:
|
||||
// NOTE(marius): this is an ugly way of dealing with the interface conversion error: types from different scopes
|
||||
typ := reflect.TypeOf(new(Repository))
|
||||
if i, ok := reflect.ValueOf(it).Convert(typ).Interface().(*Repository); ok {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
return nil, ap.ErrorInvalidType[ap.Actor](it)
|
||||
}
|
||||
|
||||
type withRepositoryFn func(*Repository) error
|
||||
|
||||
// OnRepository calls function fn on it Item if it can be asserted to type *Repository
|
||||
func OnRepository(it ap.Item, fn withRepositoryFn) error {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
ob, err := ToRepository(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fn(ob)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
package forgefed
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
ap "github.com/go-ap/activitypub"
|
||||
"github.com/valyala/fastjson"
|
||||
|
@ -48,44 +50,82 @@ func (t Ticket) MarshalJSON() ([]byte, error) {
|
|||
|
||||
b = b[:len(b)-1]
|
||||
if t.Dependants != nil {
|
||||
ap.WriteItemCollectionJSONProp(&b, "dependants", t.Dependants)
|
||||
ap.JSONWriteItemCollectionJSONProp(&b, "dependants", t.Dependants)
|
||||
}
|
||||
if t.Dependencies != nil {
|
||||
ap.WriteItemCollectionJSONProp(&b, "dependencies", t.Dependencies)
|
||||
ap.JSONWriteItemCollectionJSONProp(&b, "dependencies", t.Dependencies)
|
||||
}
|
||||
ap.WriteBoolJSONProp(&b, "isResolved", t.IsResolved)
|
||||
ap.JSONWriteBoolJSONProp(&b, "isResolved", t.IsResolved)
|
||||
if t.ResolvedBy != nil {
|
||||
ap.WriteItemJSONProp(&b, "resolvedBy", t.ResolvedBy)
|
||||
ap.JSONWriteItemJSONProp(&b, "resolvedBy", t.ResolvedBy)
|
||||
}
|
||||
if !t.Resolved.IsZero() {
|
||||
ap.WriteTimeJSONProp(&b, "resolved", t.Resolved)
|
||||
ap.JSONWriteTimeJSONProp(&b, "resolved", t.Resolved)
|
||||
}
|
||||
if t.Origin != nil {
|
||||
ap.WriteItemJSONProp(&b, "origin", t.Origin)
|
||||
ap.JSONWriteItemJSONProp(&b, "origin", t.Origin)
|
||||
}
|
||||
if t.Target != nil {
|
||||
ap.WriteItemJSONProp(&b, "target", t.Target)
|
||||
ap.JSONWriteItemJSONProp(&b, "target", t.Target)
|
||||
}
|
||||
ap.Write(&b, '}')
|
||||
ap.JSONWrite(&b, '}')
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func JSONLoadTicket(val *fastjson.Value, t *Ticket) error {
|
||||
ap.OnObject(&t.Object, func(o *ap.Object) error {
|
||||
return ap.JSONLoadObject(val, o)
|
||||
})
|
||||
t.Dependants = ap.JSONGetItems(val, "dependants")
|
||||
t.Dependencies = ap.JSONGetItems(val, "dependencies")
|
||||
t.IsResolved = ap.JSONGetBoolean(val, "isResolved")
|
||||
t.ResolvedBy = ap.JSONGetItem(val, "resolvedBy")
|
||||
t.Resolved = ap.JSONGetTime(val, "resolved")
|
||||
t.Origin = ap.JSONGetItem(val, "origin")
|
||||
t.Target = ap.JSONGetItem(val, "target")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Ticket) UnmarshalJSON(data []byte) error {
|
||||
p := fastjson.Parser{}
|
||||
val, err := p.ParseBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Dependants = ap.JSONGetItems(val, "dependants")
|
||||
t.Dependencies = ap.JSONGetItems(val, "dependencies")
|
||||
t.IsResolved = ap.JSONGetBoolean(val, "isResolved")
|
||||
t.ResolvedBy = ap.JSONGetItem(val, "resolvedBy")
|
||||
t.Resolved = ap.JSONGetTime(val, "resolved")
|
||||
t.Origin = ap.JSONGetItem(val, "origin")
|
||||
t.Target = ap.JSONGetItem(val, "target")
|
||||
|
||||
return ap.OnObject(&t.Object, func(a *ap.Object) error {
|
||||
return ap.LoadObject(val, a)
|
||||
})
|
||||
return JSONLoadTicket(val, t)
|
||||
}
|
||||
|
||||
// ToTicket tries to convert the it Item to a Ticket object.
|
||||
func ToTicket(it ap.Item) (*Ticket, error) {
|
||||
switch i := it.(type) {
|
||||
case *Ticket:
|
||||
return i, nil
|
||||
case Ticket:
|
||||
return &i, nil
|
||||
case *ap.Object:
|
||||
return (*Ticket)(unsafe.Pointer(i)), nil
|
||||
case ap.Object:
|
||||
return (*Ticket)(unsafe.Pointer(&i)), nil
|
||||
default:
|
||||
// NOTE(marius): this is an ugly way of dealing with the interface conversion error: types from different scopes
|
||||
typ := reflect.TypeOf(new(Ticket))
|
||||
if i, ok := reflect.ValueOf(it).Convert(typ).Interface().(*Ticket); ok {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
return nil, ap.ErrorInvalidType[ap.Object](it)
|
||||
}
|
||||
|
||||
type withTicketFn func(*Ticket) error
|
||||
|
||||
// OnTicket calls function fn on it Item if it can be asserted to type *Ticket
|
||||
func OnTicket(it ap.Item, fn withTicketFn) error {
|
||||
if it == nil {
|
||||
return nil
|
||||
}
|
||||
ob, err := ToTicket(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fn(ob)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue