Added gob Marshal/Unmarshal for Link type

Testing is still incomplete for this
This commit is contained in:
mariusor 2021-12-30 19:01:15 +01:00
parent a7d54ee31e
commit 525748448c
No known key found for this signature in database
GPG key ID: DBF5E47F5DBC4D21
2 changed files with 239 additions and 6 deletions

145
link.go
View file

@ -1,6 +1,9 @@
package activitypub
import (
"bytes"
"encoding/gob"
"errors"
"fmt"
"github.com/valyala/fastjson"
@ -116,20 +119,150 @@ func (l *Link) UnmarshalJSON(data []byte) error {
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
func (l *Link) UnmarshalBinary(data []byte) error {
return fmt.Errorf("UnmarshalBinary is not implemented for %T", *l)
return l.GobDecode(data)
}
/*
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (l Link) MarshalBinary() ([]byte, error) {
return nil, errors.New(fmt.Sprintf("MarshalBinary is not implemented for %T", l))
return l.GobEncode()
}
// TODO(marius): when migrating to go1.18, use a numeric constraint for this
func gobEncodeUint(i uint) ([]byte, error) {
b := bytes.Buffer{}
gg := gob.NewEncoder(&b)
if err := gg.Encode(i); err != nil {
return nil, err
}
return b.Bytes(), nil
}
func (l Link) GobEncode() ([]byte, error) {
return nil, errors.New(fmt.Sprintf("GobEncode is not implemented for %T", l))
var (
mm = make(map[string][]byte)
err error
hasData bool
)
if len(l.ID) > 0 {
if mm["id"], err = l.ID.GobEncode(); err != nil {
return nil, err
}
hasData = true
}
if len(l.Type) > 0 {
if mm["type"], err = l.Type.GobEncode(); err != nil {
return nil, err
}
hasData = true
}
if len(l.MediaType) > 0 {
if mm["mediaType"], err = l.MediaType.GobEncode(); err != nil {
return nil, err
}
hasData = true
}
if len(l.Href) > 0 {
if mm["href"], err = l.Href.GobEncode(); err != nil {
return nil, err
}
hasData = true
}
if len(l.HrefLang) > 0 {
if mm["hrefLang"], err = l.HrefLang.GobEncode(); err != nil {
return nil, err
}
hasData = true
}
if len(l.Name) > 0 {
if mm["name"], err = l.Name.GobEncode(); err != nil {
return nil, err
}
hasData = true
}
if len(l.Rel) > 0 {
if mm["rel"], err = l.Rel.GobEncode(); err != nil {
return nil, err
}
hasData = true
}
if l.Width > 0 {
if mm["width"], err = gobEncodeUint(l.Width); err != nil {
return nil, err
}
hasData = true
}
if l.Height > 0 {
if mm["height"], err = gobEncodeUint(l.Height); err != nil {
return nil, err
}
hasData = true
}
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 (l *Link) GobDecode([]byte) error {
func gobDecodeUint(i *uint, data []byte) error {
g := gob.NewDecoder(bytes.NewReader(data))
return g.Decode(i)
}
func (l *Link) GobDecode(data []byte) error {
mm := make(map[string][]byte)
g := gob.NewDecoder(bytes.NewReader(data))
if err := g.Decode(&mm); err != nil {
return err
}
if raw, ok := mm["id"]; ok {
if err := l.ID.GobDecode(raw); err != nil {
return err
}
}
if raw, ok := mm["type"]; ok {
if err := l.Type.GobDecode(raw); err != nil {
return err
}
}
if raw, ok := mm["mediaType"]; ok {
if err := l.MediaType.GobDecode(raw); err != nil {
return err
}
}
if raw, ok := mm["href"]; ok {
if err := l.Href.GobDecode(raw); err != nil {
return err
}
}
if raw, ok := mm["hrefLang"]; ok {
if err := l.HrefLang.GobDecode(raw); err != nil {
return err
}
}
if raw, ok := mm["name"]; ok {
if err := l.Name.GobDecode(raw); err != nil {
return err
}
}
if raw, ok := mm["rel"]; ok {
if err := l.Rel.GobDecode(raw); err != nil {
return err
}
}
if raw, ok := mm["width"]; ok {
if err := gobDecodeUint(&l.Width, raw); err != nil {
return err
}
}
if raw, ok := mm["height"]; ok {
if err := gobDecodeUint(&l.Height, raw); err != nil {
return err
}
}
return errors.New(fmt.Sprintf("GobDecode is not implemented for %T", *l))
}
*/

View file

@ -1,6 +1,7 @@
package activitypub
import (
"reflect"
"testing"
)
@ -63,3 +64,102 @@ func TestMentionNew(t *testing.T) {
func TestLink_IsCollection(t *testing.T) {
t.Skipf("TODO")
}
func TestLink_GobEncode(t *testing.T) {
type fields struct {
ID ID
Type ActivityVocabularyType
Name NaturalLanguageValues
Rel IRI
MediaType MimeType
Height uint
Width uint
Preview Item
Href IRI
HrefLang LangRef
}
tests := []struct {
name string
fields fields
want []byte
wantErr bool
}{
{
name: "empty",
fields: fields{},
want: []byte{},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := Link{
ID: tt.fields.ID,
Type: tt.fields.Type,
Name: tt.fields.Name,
Rel: tt.fields.Rel,
MediaType: tt.fields.MediaType,
Height: tt.fields.Height,
Width: tt.fields.Width,
Preview: tt.fields.Preview,
Href: tt.fields.Href,
HrefLang: tt.fields.HrefLang,
}
got, err := l.GobEncode()
if (err != nil) != tt.wantErr {
t.Errorf("GobEncode() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GobEncode() got = %v, want %v", got, tt.want)
}
})
}
}
func TestLink_GobDecode(t *testing.T) {
type fields struct {
ID ID
Type ActivityVocabularyType
Name NaturalLanguageValues
Rel IRI
MediaType MimeType
Height uint
Width uint
Preview Item
Href IRI
HrefLang LangRef
}
tests := []struct {
name string
fields fields
data []byte
wantErr bool
}{
{
name: "empty",
fields: fields{},
data: []byte{},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
l := &Link{
ID: tt.fields.ID,
Type: tt.fields.Type,
Name: tt.fields.Name,
Rel: tt.fields.Rel,
MediaType: tt.fields.MediaType,
Height: tt.fields.Height,
Width: tt.fields.Width,
Preview: tt.fields.Preview,
Href: tt.fields.Href,
HrefLang: tt.fields.HrefLang,
}
if err := l.GobDecode(tt.data); (err != nil) != tt.wantErr {
t.Errorf("GobDecode() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}