353 lines
7.1 KiB
Go
353 lines
7.1 KiB
Go
package twt_pb
|
|
|
|
import (
|
|
"io"
|
|
"iter"
|
|
"slices"
|
|
"time"
|
|
|
|
"go.yarn.social/lextwt"
|
|
"go.yarn.social/types"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
type twtRegistry interface {
|
|
Twters() []*types.Twter
|
|
Preamble() lextwt.Comments
|
|
Twts() types.Twts
|
|
WriteTo(w io.Writer) (int64, error)
|
|
}
|
|
|
|
func EncodeRegistry(r twtRegistry) ([]byte, error) {
|
|
o := &TwtRegistry{}
|
|
o.FromLextwt(r)
|
|
|
|
return proto.Marshal(o)
|
|
}
|
|
func DecodeRegistry(b []byte) (twtRegistry, error) {
|
|
o := &TwtRegistry{}
|
|
err := proto.Unmarshal(b, o)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return o.ToLextwt(), nil
|
|
}
|
|
|
|
func (r *TwtRegistry) FromLextwt(twt twtRegistry) error {
|
|
preamble := twt.Preamble()
|
|
r.Preamble = apply(
|
|
slices.All(preamble),
|
|
make([]*Comment, len(preamble)),
|
|
fromComment)
|
|
|
|
twts := twt.Twts()
|
|
r.Twts = apply(
|
|
slices.All(twts),
|
|
make([]*Twt, len(twts)),
|
|
fromTwt)
|
|
|
|
return nil
|
|
}
|
|
func (r *TwtRegistry) ToLextwt() twtRegistry {
|
|
return lextwt.NewTwtRegistry(
|
|
apply(slices.All(r.Preamble), make(lextwt.Comments, len(r.Preamble)), func(c *Comment) *lextwt.Comment {
|
|
return c.ToLextwt()
|
|
}),
|
|
apply(slices.All(r.Twts), make(types.Twts, len(r.Twts)), func(c *Twt) types.Twt {
|
|
return c.ToLextwt()
|
|
}),
|
|
)
|
|
}
|
|
|
|
type twtFeed interface {
|
|
Twter() *types.Twter
|
|
Preamble() lextwt.Comments
|
|
Twts() types.Twts
|
|
WriteTo(w io.Writer) (int64, error)
|
|
}
|
|
|
|
func EncodeFeed(r twtFeed) ([]byte, error) {
|
|
o := &TwtFeed{}
|
|
o.FromLextwt(r)
|
|
|
|
return proto.Marshal(o)
|
|
}
|
|
func DecodeFeed(b []byte) (twtFeed, error) {
|
|
o := &TwtFeed{}
|
|
err := proto.Unmarshal(b, o)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return o.ToLextwt(), nil
|
|
}
|
|
|
|
func (r *TwtFeed) FromLextwt(twt twtFeed) error {
|
|
r.Twter = fromTwter(twt.Twter())
|
|
preamble := twt.Preamble()
|
|
r.Preamble = apply(
|
|
slices.All(preamble),
|
|
make([]*Comment, len(preamble)),
|
|
fromComment)
|
|
|
|
twts := twt.Twts()
|
|
r.Twts = apply(
|
|
slices.All(twts),
|
|
make([]*Twt, len(twts)),
|
|
fromTwt)
|
|
|
|
return nil
|
|
}
|
|
func (r *TwtFeed) ToLextwt() twtFeed {
|
|
return lextwt.NewTwtFile(
|
|
*r.Twter.ToLextwt(),
|
|
apply(slices.All(r.Preamble), make(lextwt.Comments, len(r.Preamble)), func(c *Comment) *lextwt.Comment {
|
|
return c.ToLextwt()
|
|
}),
|
|
apply(slices.All(r.Twts), make(types.Twts, len(r.Twts)), func(c *Twt) types.Twt {
|
|
return c.ToLextwt()
|
|
}),
|
|
)
|
|
}
|
|
|
|
|
|
func apply[U, V any](u iter.Seq2[int, U], v []V, fn func(U) V) []V {
|
|
for i, u := range u {
|
|
v[i] = fn(u)
|
|
}
|
|
return v
|
|
|
|
}
|
|
|
|
func (e *Twter) FromLextwt(twt *types.Twter) {
|
|
e.Nick = twt.Nick
|
|
e.Uri = twt.URI
|
|
}
|
|
func fromTwter(twt *types.Twter) *Twter {
|
|
return &Twter{
|
|
Nick: twt.Nick,
|
|
Uri: twt.URI,
|
|
}
|
|
}
|
|
func (e *Twter) ToLextwt() *types.Twter {
|
|
return &types.Twter{
|
|
Nick: e.Nick,
|
|
URI: e.Uri,
|
|
}
|
|
}
|
|
|
|
func (e *Twt) FromLextwt(twt *lextwt.Twt) {
|
|
twter := twt.Twter()
|
|
|
|
e.Twter.FromLextwt(&twter)
|
|
e.Created = fromDateTime(twt.Created())
|
|
e.Msg = apply(
|
|
slices.All(twt.Elems()),
|
|
make([]*Elem, len(twt.Elems())),
|
|
fromElem,
|
|
)
|
|
}
|
|
func fromTwt(twt types.Twt) *Twt {
|
|
twter := twt.Twter()
|
|
lx, ok := twt.(*lextwt.Twt)
|
|
if !ok {
|
|
return &Twt{}
|
|
}
|
|
|
|
msg := lx.Elems()
|
|
return &Twt{
|
|
Twter: fromTwter(&twter),
|
|
Created: fromDateTime(twt.Created()),
|
|
Msg: apply(
|
|
slices.All(msg),
|
|
make([]*Elem, len(msg)),
|
|
fromElem,
|
|
),
|
|
}
|
|
}
|
|
func (e *Twt) ToLextwt() *lextwt.Twt {
|
|
return lextwt.NewTwt(
|
|
*e.Twter.ToLextwt(),
|
|
e.Created.ToLextwt(),
|
|
apply(
|
|
slices.All(e.Msg),
|
|
make([]lextwt.Elem, len(e.Msg)),
|
|
func(e *Elem) lextwt.Elem {
|
|
return e.ToLextwt()
|
|
},
|
|
)...,
|
|
)
|
|
}
|
|
|
|
func fromDateTime(t time.Time) *DateTime {
|
|
zone, offset := t.Zone()
|
|
return &DateTime{
|
|
Timestamp: t.UnixMicro(),
|
|
Offset: int32(offset),
|
|
Zone: zone,
|
|
}
|
|
}
|
|
func (c *DateTime) ToLextwt() *lextwt.DateTime {
|
|
dt := time.UnixMicro(c.Timestamp)
|
|
dt = dt.In(time.FixedZone(c.Zone, int(c.Offset)))
|
|
return lextwt.NewDateTime(dt, dt.Format(time.RFC3339))
|
|
}
|
|
|
|
func fromElem(e lextwt.Elem) *Elem {
|
|
if e == lextwt.LineSeparator {
|
|
return &Elem{Elem: &Elem_Lineseparator{fromLineSeparator()}}
|
|
}
|
|
|
|
switch e := e.(type) {
|
|
case *lextwt.BangMention:
|
|
return &Elem{Elem: &Elem_Bangmention{fromBangMention(e)}}
|
|
|
|
case *lextwt.Code:
|
|
return &Elem{Elem: &Elem_Code{fromCode(e)}}
|
|
|
|
case *lextwt.Comment:
|
|
return &Elem{Elem: &Elem_Comment{fromComment(e)}}
|
|
|
|
case *lextwt.Mention:
|
|
return &Elem{Elem: &Elem_Mention{fromMention(e)}}
|
|
|
|
case *lextwt.Subject:
|
|
return &Elem{Elem: &Elem_Subject{fromSubject(e)}}
|
|
|
|
case *lextwt.Tag:
|
|
return &Elem{Elem: &Elem_Tag{fromTag(e)}}
|
|
|
|
case *lextwt.Link:
|
|
return &Elem{Elem: &Elem_Link{fromLink(e)}}
|
|
|
|
case *lextwt.Text:
|
|
return &Elem{Elem: &Elem_Text{fromText(e)}}
|
|
}
|
|
|
|
return &Elem{}
|
|
}
|
|
func (c *Elem) ToLextwt() lextwt.Elem {
|
|
switch e := c.Elem.(type) {
|
|
case *Elem_Bangmention:
|
|
return e.Bangmention.ToLextwt()
|
|
case *Elem_Code:
|
|
return e.Code.ToLextwt()
|
|
case *Elem_Comment:
|
|
return e.Comment.ToLextwt()
|
|
case *Elem_Lineseparator:
|
|
return e.Lineseparator.ToLextwt()
|
|
case *Elem_Link:
|
|
return e.Link.ToLextwt()
|
|
case *Elem_Mention:
|
|
return e.Mention.ToLextwt()
|
|
case *Elem_Subject:
|
|
return e.Subject.ToLextwt()
|
|
case *Elem_Tag:
|
|
return e.Tag.ToLextwt()
|
|
case *Elem_Text:
|
|
return e.Text.ToLextwt()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func fromCode(c *lextwt.Code) *Code {
|
|
return &Code{
|
|
Type: Code_Type(c.CodeType()),
|
|
Code: c.Text(),
|
|
}
|
|
}
|
|
func (c *Code) ToLextwt() *lextwt.Code {
|
|
return lextwt.NewCode(c.Code, lextwt.CodeType(c.Type))
|
|
}
|
|
|
|
func fromComment(c *lextwt.Comment) *Comment {
|
|
return &Comment{
|
|
Comment: c.Text(),
|
|
Key: c.Key(),
|
|
Value: c.Value(),
|
|
}
|
|
}
|
|
func (c *Comment) ToLextwt() *lextwt.Comment {
|
|
if c.Key != "" {
|
|
return lextwt.NewCommentValue(c.Comment, c.Key, c.Value)
|
|
}
|
|
return lextwt.NewComment(c.Comment)
|
|
}
|
|
|
|
func fromBangMention(c *lextwt.BangMention) *BangMention {
|
|
return &BangMention{
|
|
Name: c.Name(),
|
|
Target: c.Target(),
|
|
}
|
|
}
|
|
func (c *BangMention) ToLextwt() *lextwt.BangMention {
|
|
return lextwt.NewBangMention(c.Name, c.Target)
|
|
}
|
|
|
|
func fromMention(c *lextwt.Mention) *Mention {
|
|
return &Mention{
|
|
Name: c.Name(),
|
|
Target: c.Target(),
|
|
}
|
|
}
|
|
func (c *Mention) ToLextwt() *lextwt.Mention {
|
|
return lextwt.NewMention(c.Name, c.Target)
|
|
}
|
|
|
|
func fromTag(c *lextwt.Tag) *Tag {
|
|
return &Tag{
|
|
Tag: c.Text(),
|
|
Target: c.Target(),
|
|
}
|
|
}
|
|
func (c *Tag) ToLextwt() *lextwt.Tag {
|
|
return lextwt.NewTag(c.Tag, c.Target)
|
|
}
|
|
|
|
func fromLineSeparator() *LineSeparator {
|
|
return &LineSeparator{}
|
|
}
|
|
func (c *LineSeparator) ToLextwt() lextwt.Elem {
|
|
return lextwt.LineSeparator
|
|
}
|
|
|
|
func fromLink(c *lextwt.Link) *Link {
|
|
return &Link{
|
|
Type: Link_Type(c.LinkType()),
|
|
Alt: c.Text(),
|
|
Target: c.Target(),
|
|
Title: c.Title(),
|
|
}
|
|
}
|
|
func (c *Link) ToLextwt() *lextwt.Link {
|
|
if c.Type == Link_Type(lextwt.LinkMedia) {
|
|
return lextwt.NewMedia(c.Alt, c.Target, c.Title)
|
|
}
|
|
return lextwt.NewLink(c.Alt, c.Target, lextwt.LinkType(c.Type))
|
|
}
|
|
|
|
func fromSubject(c *lextwt.Subject) *Subject {
|
|
if tag, ok := c.Tag().(*lextwt.Tag); ok {
|
|
return &Subject{
|
|
Tag: fromTag(tag),
|
|
}
|
|
}
|
|
return &Subject{
|
|
Subject: c.Text(),
|
|
}
|
|
}
|
|
func (c *Subject) ToLextwt() *lextwt.Subject {
|
|
if c.Tag != nil {
|
|
return lextwt.NewSubjectTag(c.Tag.Tag, c.Tag.Target)
|
|
}
|
|
return lextwt.NewSubject(c.Subject)
|
|
}
|
|
|
|
func fromText(c *lextwt.Text) *Text {
|
|
return &Text{
|
|
Text: c.Literal(),
|
|
}
|
|
}
|
|
func (c *Text) ToLextwt() *lextwt.Text {
|
|
return lextwt.NewText(c.Text)
|
|
}
|