diff --git a/ent/errors.go b/ent/errors.go index e266819..5ab64a9 100644 --- a/ent/errors.go +++ b/ent/errors.go @@ -6,4 +6,5 @@ import ( const ( errNilReceiver = erorr.Error("mstdn/ent: nil receiver") + errNothingID = erorr.Error("mstdn/ent: nothing id") ) diff --git a/ent/status.go b/ent/status.go index 8aa17df..aa5c0c6 100644 --- a/ent/status.go +++ b/ent/status.go @@ -3,6 +3,7 @@ package ent import ( "encoding/json" + "github.com/reiver/go-erorr" "github.com/reiver/go-jsonint" "github.com/reiver/go-opt" "github.com/reiver/go-nul" @@ -41,3 +42,298 @@ type Status struct { Pinned opt.Optional[bool] `json:"pinned"` Filtered json.RawMessage `json:"filtered"` } + +func (receiver *Status) MarshalJSON() ([]byte, error) { + if nil == receiver { + return nil, errNilReceiver + } + + var buffer [1024]byte + var p []byte = buffer[0:0] + + p = append(p, '{') + + { + val, found := receiver.ID.Get() + if !found { + return nil, errNothingID + } + + const name = "id" + p = append(p, `"id":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + + { + val, found := receiver.URI.Get() + if found { + const name = "uri" + p = append(p, `,"uri":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.URL.Get() + if found { + const name = "url" + p = append(p, `,"url":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.CreatedAt.Get() + if found { + const name = "created_at" + p = append(p, `,"created_at":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + +//@TODO: Account + + { + val, found := receiver.Content.Get() + if found { + const name = "content" + p = append(p, `,"content":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Visibility.Get() + if found { + const name = "visibility" + p = append(p, `,"visibility":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Sensitive.Get() + if found { + const name = "sensitive" + p = append(p, `,"sensitive":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.SpoilerText.Get() + if found { + const name = "spoiler_text" + p = append(p, `,"spoiler_text":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + +//@TODO: MediaAttachments + +//@TODO: Application + +//@TODO: Mentions + +//@TODO: Tags + +//@TODO: Emojis + +//@TODO: ReblogsCount + +//@TODO: FavouritesCount + +//@TODO: RepliesCount + +//@TODO: InReplyToID + +//@TODO: InReplyToAccountID + +//@TODO: Reblog + +//@TODO: Poll + +//@TODO: Card + + { + val, found := receiver.Language.Get() + if found { + const name = "language" + p = append(p, `,"language":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Text.Get() + if found { + const name = "text" + p = append(p, `,"text":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.EditedAt.Get() + if found { + const name = "edited_at" + p = append(p, `,"edited_at":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Favourited.Get() + if found { + const name = "favourited" + p = append(p, `,"favourited":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Reblogged.Get() + if found { + const name = "reblogged" + p = append(p, `,"reblogged":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Muted.Get() + if found { + const name = "muted" + p = append(p, `,"muted":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Bookmarked.Get() + if found { + const name = "bookmarked" + p = append(p, `,"bookmarked":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + val, found := receiver.Pinned.Get() + if found { + const name = "pinned" + p = append(p, `,"pinned":`...) + + bytes, err := json.Marshal(val) + if nil != err { + return nil, erorr.Errorf("problem marshaling %q: %w", name, err) + } + + p = append(p, bytes...) + } + } + + { + bytes := []byte(receiver.Filtered) + if 0 < len(bytes) { + const name = "filtered" + p = append(p, `,"filtered":`...) + + p = append(p, bytes...) + } + } + + p = append(p, '}') + + return p, nil +} diff --git a/ent/status_marshaljson_test.go b/ent/status_marshaljson_test.go new file mode 100644 index 0000000..91761ef --- /dev/null +++ b/ent/status_marshaljson_test.go @@ -0,0 +1,180 @@ +package ent + +import ( + "testing" + + "encoding/json" + + "github.com/reiver/go-nul" + "github.com/reiver/go-opt" +) + +func TestStatus_JSON(t *testing.T) { + + tests := []struct{ + Status Status + Expected string + }{ + { + Status:Status{ + ID: opt.Something("123"), + }, + Expected: `{"id":"123"}`, + }, + + + + { + Status:Status{ + ID: opt.Something("123"), + URI: nul.Something("https://example.com/status/123"), + }, + Expected: `{"id":"123","uri":"https://example.com/status/123"}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + URL: nul.Something("https://example.com/@joeblow/status/123"), + }, + Expected: `{"id":"123","url":"https://example.com/@joeblow/status/123"}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + CreatedAt: opt.Something("yesterday"), + }, + Expected: `{"id":"123","created_at":"yesterday"}`, + }, +//@TODO: Account + { + Status:Status{ + ID: opt.Something("123"), + Content: opt.Something("Hello world!"), + }, + Expected: `{"id":"123","content":"Hello world!"}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Visibility: opt.Something("public"), + }, + Expected: `{"id":"123","visibility":"public"}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Sensitive: opt.Something(true), + }, + Expected: `{"id":"123","sensitive":true}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + SpoilerText: opt.Something("the rabbit did it"), + }, + Expected: `{"id":"123","spoiler_text":"the rabbit did it"}`, + }, +//@TODO: MediaAttachments +//@TODO: Application +//@TODO: Mentions +//@TODO: Tags +//@TODO: Emojis + + + + + + + + + + { + Status:Status{ + ID: opt.Something("123"), + Language: nul.Something("en"), + }, + Expected: `{"id":"123","language":"en"}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Text: nul.Something("bing bong bang"), + }, + Expected: `{"id":"123","text":"bing bong bang"}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + EditedAt: nul.Something("today"), + }, + Expected: `{"id":"123","edited_at":"today"}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Favourited: opt.Something(true), + }, + Expected: `{"id":"123","favourited":true}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Reblogged: opt.Something(true), + }, + Expected: `{"id":"123","reblogged":true}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Muted: opt.Something(true), + }, + Expected: `{"id":"123","muted":true}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Bookmarked: opt.Something(true), + }, + Expected: `{"id":"123","bookmarked":true}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Pinned: opt.Something(true), + }, + Expected: `{"id":"123","pinned":true}`, + }, + { + Status:Status{ + ID: opt.Something("123"), + Filtered: json.RawMessage([]byte(`{"once":1,"twice":2,"thrice":3,"fource":4}`)), + }, + Expected: `{"id":"123","filtered":{"once":1,"twice":2,"thrice":3,"fource":4}}`, + }, + } + + for testNumber, test := range tests { + + actualBytes, err := json.Marshal(&test.Status) + + if nil != err { + t.Errorf("For test #%d, did not expect to get an error but actually did.", testNumber) + t.Logf("ERROR: (%T) %s", err, err) + continue + } + + actual := string(actualBytes) + + expected := test.Expected + + if expected != actual { + t.Errorf("For test #%d, the actual string-serialized form is not what was expected.", testNumber) + t.Logf("EXPECTED: %q", expected) + t.Logf("ACTUAL: %q", actual) + t.Logf("EXPECTED:\n%s", expected) + t.Logf("ACTUAL:\n%s", actual) + t.Logf("STATUS:\n%v", test.Status) + continue + } + } +}