Adding gob encoding for an object
This commit is contained in:
parent
30317634f5
commit
98500a23a4
377
object.go
377
object.go
|
@ -309,32 +309,389 @@ func (o Object) MarshalJSON() ([]byte, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
/*
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||
func (o *Object) UnmarshalBinary(data []byte) error {
|
||||
return errors.New(fmt.Sprintf("UnmarshalBinary is not implemented for %T", *o))
|
||||
return o.GobDecode(data)
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||
func (o Object) MarshalBinary() ([]byte, error) {
|
||||
w := &bytes.Buffer{}
|
||||
enc := gobEncoder{ w: w, enc: gob.NewEncoder(w) }
|
||||
if _, err := enc.writeObjectGobValue(o); err != nil {
|
||||
return nil, err
|
||||
return o.GobEncode()
|
||||
}
|
||||
|
||||
func gobDecodeItem(it Item, data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func gobEncodeItemCollection(g *gob.Encoder, col ItemCollection) error {
|
||||
return g.Encode(col)
|
||||
}
|
||||
|
||||
func gobEncodeItem(it Item) ([]byte, error) {
|
||||
b := bytes.Buffer{}
|
||||
var err error
|
||||
if IsIRI(it) {
|
||||
g := gob.NewEncoder(&b)
|
||||
err = gobEncodeStringLikeType(g, []byte(it.GetLink()))
|
||||
}
|
||||
return w.Bytes(), nil
|
||||
if IsItemCollection(it) {
|
||||
g := gob.NewEncoder(&b)
|
||||
err = OnItemCollection(it, func(col *ItemCollection) error {
|
||||
return gobEncodeItemCollection(g, *col)
|
||||
})
|
||||
}
|
||||
switch it.GetType() {
|
||||
case "", ObjectType, ArticleType, AudioType, DocumentType, EventType, ImageType, NoteType, PageType, VideoType:
|
||||
err = OnObject(it, func(ob *Object) error {
|
||||
bytes, err := ob.GobEncode()
|
||||
b.Write(bytes)
|
||||
return err
|
||||
})
|
||||
case LinkType, MentionType:
|
||||
err = OnLink(it, func(l *Link) error {
|
||||
bytes, err := l.GobEncode()
|
||||
b.Write(bytes)
|
||||
return err
|
||||
})
|
||||
case ActivityType, AcceptType, AddType, AnnounceType, BlockType, CreateType, DeleteType, DislikeType,
|
||||
FlagType, FollowType, IgnoreType, InviteType, JoinType, LeaveType, LikeType, ListenType, MoveType, OfferType,
|
||||
RejectType, ReadType, RemoveType, TentativeRejectType, TentativeAcceptType, UndoType, UpdateType, ViewType:
|
||||
err = OnActivity(it, func(act *Activity) error {
|
||||
bytes, err := act.GobEncode()
|
||||
b.Write(bytes)
|
||||
return err
|
||||
})
|
||||
case IntransitiveActivityType, ArriveType, TravelType:
|
||||
err = OnIntransitiveActivity(it, func(act *IntransitiveActivity) error {
|
||||
bytes, err := act.GobEncode()
|
||||
b.Write(bytes)
|
||||
return err
|
||||
})
|
||||
case ActorType, ApplicationType, GroupType, OrganizationType, PersonType, ServiceType:
|
||||
err = OnActor(it, func(a *Actor) error {
|
||||
bytes, err := a.GobEncode()
|
||||
b.Write(bytes)
|
||||
return err
|
||||
})
|
||||
case CollectionType:
|
||||
err = OnCollection(it, func(c *Collection) error {
|
||||
return nil
|
||||
})
|
||||
case OrderedCollectionType:
|
||||
err = OnOrderedCollection(it, func(c *OrderedCollection) error {
|
||||
return nil
|
||||
})
|
||||
case CollectionPageType:
|
||||
err = OnCollectionPage(it, func(p *CollectionPage) error {
|
||||
return nil
|
||||
})
|
||||
case OrderedCollectionPageType:
|
||||
err = OnOrderedCollectionPage(it, func(p *OrderedCollectionPage) error {
|
||||
return nil
|
||||
})
|
||||
case PlaceType:
|
||||
err = OnPlace(it, func(p *Place) error {
|
||||
return nil
|
||||
})
|
||||
case ProfileType:
|
||||
err = OnProfile(it, func(p *Profile) error {
|
||||
return nil
|
||||
})
|
||||
case RelationshipType:
|
||||
err = OnRelationship(it, func(r *Relationship) error {
|
||||
return nil
|
||||
})
|
||||
case TombstoneType:
|
||||
err = OnTombstone(it, func(t *Tombstone) error {
|
||||
return nil
|
||||
})
|
||||
case QuestionType:
|
||||
err = OnQuestion(it, func(q *Question) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return b.Bytes(), err
|
||||
}
|
||||
|
||||
func mapObjectProperties(mm map[string][]byte, o *Object) (hasData bool, err error) {
|
||||
if len(o.ID) > 0 {
|
||||
if mm["id"], err = o.ID.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if len(o.Type) > 0 {
|
||||
if mm["type"], err = o.Type.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if len(o.MediaType) > 0 {
|
||||
if mm["mediaType"], err = o.MediaType.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if len(o.Name) > 0 {
|
||||
if mm["name"], err = o.Name.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Attachment != nil {
|
||||
if mm["attachment"], err = gobEncodeItem(o.Attachment); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.AttributedTo != nil {
|
||||
if mm["attributedTo"], err = gobEncodeItem(o.AttributedTo); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Audience != nil {
|
||||
if mm["audience"], err = gobEncodeItem(o.Audience); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Content != nil {
|
||||
if mm["content"], err = o.Content.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Context != nil {
|
||||
if mm["context"], err = gobEncodeItem(o.Context); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if len(o.MediaType) > 0 {
|
||||
if mm["mediaType"], err = o.MediaType.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if !o.EndTime.IsZero() {
|
||||
if mm["endTime"], err = o.EndTime.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Generator != nil {
|
||||
if mm["generator"], err = gobEncodeItem(o.Generator); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Icon != nil {
|
||||
if mm["icon"], err = gobEncodeItem(o.Icon); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Image != nil {
|
||||
if mm["image"], err = gobEncodeItem(o.Image); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.InReplyTo != nil {
|
||||
if mm["inReplyTo"], err = gobEncodeItem(o.InReplyTo); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Location != nil {
|
||||
if mm["location"], err = gobEncodeItem(o.Location); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Preview != nil {
|
||||
if mm["preview"], err = gobEncodeItem(o.Preview); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if !o.Published.IsZero() {
|
||||
if mm["published"], err = o.Published.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Replies != nil {
|
||||
if mm["replies"], err = gobEncodeItem(o.Replies); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if !o.StartTime.IsZero() {
|
||||
if mm["startTime"], err = o.StartTime.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if len(o.Summary) > 0 {
|
||||
if mm["summary"], err = o.Summary.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Tag != nil {
|
||||
if mm["tag"], err = gobEncodeItem(o.Tag); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if !o.Updated.IsZero() {
|
||||
if mm["updated"], err = o.Updated.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Tag != nil {
|
||||
if mm["tag"], err = gobEncodeItem(o.Tag); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if !o.Updated.IsZero() {
|
||||
if mm["updated"], err = o.Updated.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.URL != nil {
|
||||
if mm["url"], err = gobEncodeItem(o.URL); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.To != nil {
|
||||
if mm["to"], err = gobEncodeItem(o.To); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Bto != nil {
|
||||
if mm["bto"], err = gobEncodeItem(o.Bto); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.CC != nil {
|
||||
if mm["cc"], err = gobEncodeItem(o.CC); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.BCC != nil {
|
||||
if mm["bcc"], err = gobEncodeItem(o.BCC); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Duration > 0 {
|
||||
if mm["duration"], err = gobEncodeInt64(int64(o.Duration)); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Likes != nil {
|
||||
if mm["likes"], err = gobEncodeItem(o.Likes); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Shares != nil {
|
||||
if mm["shares"], err = gobEncodeItem(o.Shares); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if o.Shares != nil {
|
||||
if mm["shares"], err = gobEncodeItem(o.Shares); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
if len(o.Source.MediaType)+len(o.Source.Content) > 0 {
|
||||
if mm["source"], err = o.Source.GobEncode(); err != nil {
|
||||
return hasData, err
|
||||
}
|
||||
hasData = true
|
||||
}
|
||||
|
||||
return hasData, nil
|
||||
}
|
||||
|
||||
// GobEncode
|
||||
func (o Object) GobEncode() ([]byte, error) {
|
||||
return o.MarshalBinary()
|
||||
mm := make(map[string][]byte)
|
||||
hasData, err := mapObjectProperties(mm, &o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasData {
|
||||
return []byte{}, nil
|
||||
}
|
||||
bb := bytes.Buffer{}
|
||||
g := gob.NewEncoder(&bb)
|
||||
if err := g.Encode(mm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bb.Bytes(), nil
|
||||
}
|
||||
|
||||
func unmapObjectProperties(mm map[string][]byte, o *Object) error {
|
||||
if raw, ok := mm["id"]; ok {
|
||||
if err := o.ID.GobDecode(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if raw, ok := mm["type"]; ok {
|
||||
if err := o.Type.GobDecode(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if raw, ok := mm["mediaType"]; ok {
|
||||
if err := o.MediaType.GobDecode(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if raw, ok := mm["name"]; ok {
|
||||
if err := o.Name.GobDecode(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if raw, ok := mm["attachment"]; ok {
|
||||
if err := gobDecodeItem(o.Attachment, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if raw, ok := mm["source"]; ok {
|
||||
if err := o.Source.GobDecode(raw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GobDecode
|
||||
func (o *Object) GobDecode(data []byte) error {
|
||||
return o.UnmarshalBinary(data)
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
mm := make(map[string][]byte)
|
||||
g := gob.NewDecoder(bytes.NewReader(data))
|
||||
if err := g.Decode(&mm); err != nil {
|
||||
return err
|
||||
}
|
||||
return unmapObjectProperties(mm, o)
|
||||
}
|
||||
*/
|
||||
|
||||
// Recipients performs recipient de-duplication on the Object's To, Bto, CC and BCC properties
|
||||
func (o *Object) Recipients() ItemCollection {
|
||||
|
|
103
object_test.go
103
object_test.go
|
@ -1,6 +1,7 @@
|
|||
package activitypub
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -976,3 +977,105 @@ func TestObject_Equals(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestObject_GobEncode(t *testing.T) {
|
||||
type fields struct {
|
||||
ID ID
|
||||
Type ActivityVocabularyType
|
||||
Name NaturalLanguageValues
|
||||
Attachment Item
|
||||
AttributedTo Item
|
||||
Audience ItemCollection
|
||||
Content NaturalLanguageValues
|
||||
Context Item
|
||||
MediaType MimeType
|
||||
EndTime time.Time
|
||||
Generator Item
|
||||
Icon Item
|
||||
Image Item
|
||||
InReplyTo Item
|
||||
Location Item
|
||||
Preview Item
|
||||
Published time.Time
|
||||
Replies Item
|
||||
StartTime time.Time
|
||||
Summary NaturalLanguageValues
|
||||
Tag ItemCollection
|
||||
Updated time.Time
|
||||
URL Item
|
||||
To ItemCollection
|
||||
Bto ItemCollection
|
||||
CC ItemCollection
|
||||
BCC ItemCollection
|
||||
Duration time.Duration
|
||||
Likes Item
|
||||
Shares Item
|
||||
Source Source
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want []byte
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
fields: fields{},
|
||||
want: []byte{},
|
||||
wantErr: false,
|
||||
},
|
||||
// NOTE(marius): this doesn't really work because the types are not consistent between gobValue
|
||||
// and our used encoding method
|
||||
//{
|
||||
// name: "with ID",
|
||||
// fields: fields{ID: ID("https://example.com")},
|
||||
// want: gobValue(Object{ID: "https://example.com"}),
|
||||
// wantErr: false,
|
||||
//},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := Object{
|
||||
ID: tt.fields.ID,
|
||||
Type: tt.fields.Type,
|
||||
Name: tt.fields.Name,
|
||||
Attachment: tt.fields.Attachment,
|
||||
AttributedTo: tt.fields.AttributedTo,
|
||||
Audience: tt.fields.Audience,
|
||||
Content: tt.fields.Content,
|
||||
Context: tt.fields.Context,
|
||||
MediaType: tt.fields.MediaType,
|
||||
EndTime: tt.fields.EndTime,
|
||||
Generator: tt.fields.Generator,
|
||||
Icon: tt.fields.Icon,
|
||||
Image: tt.fields.Image,
|
||||
InReplyTo: tt.fields.InReplyTo,
|
||||
Location: tt.fields.Location,
|
||||
Preview: tt.fields.Preview,
|
||||
Published: tt.fields.Published,
|
||||
Replies: tt.fields.Replies,
|
||||
StartTime: tt.fields.StartTime,
|
||||
Summary: tt.fields.Summary,
|
||||
Tag: tt.fields.Tag,
|
||||
Updated: tt.fields.Updated,
|
||||
URL: tt.fields.URL,
|
||||
To: tt.fields.To,
|
||||
Bto: tt.fields.Bto,
|
||||
CC: tt.fields.CC,
|
||||
BCC: tt.fields.BCC,
|
||||
Duration: tt.fields.Duration,
|
||||
Likes: tt.fields.Likes,
|
||||
Shares: tt.fields.Shares,
|
||||
Source: tt.fields.Source,
|
||||
}
|
||||
got, err := o.GobEncode()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GobEncode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(got, tt.want) {
|
||||
t.Errorf("GobEncode() got/want =\n%v\n%v\n", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue