mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-03-18 13:53:03 +01:00
104 lines
3.1 KiB
Go
104 lines
3.1 KiB
Go
package binary
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"fmt"
|
|
|
|
"github.com/nbd-wtf/go-nostr"
|
|
)
|
|
|
|
// Deprecated -- the encoding used here is not very elegant, we'll have a better binary format later.
|
|
func Unmarshal(data []byte, evt *nostr.Event) (err error) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
err = fmt.Errorf("failed to decode binary: %v", r)
|
|
}
|
|
}()
|
|
|
|
evt.ID = hex.EncodeToString(data[0:32])
|
|
evt.PubKey = hex.EncodeToString(data[32:64])
|
|
evt.Sig = hex.EncodeToString(data[64:128])
|
|
evt.CreatedAt = nostr.Timestamp(binary.BigEndian.Uint32(data[128:132]))
|
|
evt.Kind = int(binary.BigEndian.Uint16(data[132:134]))
|
|
contentLength := int(binary.BigEndian.Uint16(data[134:136]))
|
|
evt.Content = string(data[136 : 136+contentLength])
|
|
|
|
curr := 136 + contentLength
|
|
|
|
nTags := binary.BigEndian.Uint16(data[curr : curr+2])
|
|
curr++
|
|
evt.Tags = make(nostr.Tags, nTags)
|
|
|
|
for t := range evt.Tags {
|
|
curr++
|
|
nItems := int(data[curr])
|
|
tag := make(nostr.Tag, nItems)
|
|
for i := range tag {
|
|
curr = curr + 1
|
|
itemSize := int(binary.BigEndian.Uint16(data[curr : curr+2]))
|
|
itemStart := curr + 2
|
|
item := string(data[itemStart : itemStart+itemSize])
|
|
tag[i] = item
|
|
curr = itemStart + itemSize
|
|
}
|
|
evt.Tags[t] = tag
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// Deprecated -- the encoding used here is not very elegant, we'll have a better binary format later.
|
|
func Marshal(evt *nostr.Event) ([]byte, error) {
|
|
content := []byte(evt.Content)
|
|
buf := make([]byte, 32+32+64+4+2+2+len(content)+65536+len(evt.Tags)*40 /* blergh */)
|
|
|
|
hex.Decode(buf[0:32], []byte(evt.ID))
|
|
hex.Decode(buf[32:64], []byte(evt.PubKey))
|
|
hex.Decode(buf[64:128], []byte(evt.Sig))
|
|
|
|
if evt.CreatedAt > MaxCreatedAt {
|
|
return nil, fmt.Errorf("created_at is too big: %d, max is %d", evt.CreatedAt, MaxCreatedAt)
|
|
}
|
|
binary.BigEndian.PutUint32(buf[128:132], uint32(evt.CreatedAt))
|
|
|
|
if evt.Kind > MaxKind {
|
|
return nil, fmt.Errorf("kind is too big: %d, max is %d", evt.Kind, MaxKind)
|
|
}
|
|
binary.BigEndian.PutUint16(buf[132:134], uint16(evt.Kind))
|
|
|
|
if contentLength := len(content); contentLength > MaxContentSize {
|
|
return nil, fmt.Errorf("content is too large: %d, max is %d", contentLength, MaxContentSize)
|
|
} else {
|
|
binary.BigEndian.PutUint16(buf[134:136], uint16(contentLength))
|
|
}
|
|
copy(buf[136:], content)
|
|
|
|
if tagCount := len(evt.Tags); tagCount > MaxTagCount {
|
|
return nil, fmt.Errorf("can't encode too many tags: %d, max is %d", tagCount, MaxTagCount)
|
|
} else {
|
|
binary.BigEndian.PutUint16(buf[136+len(content):136+len(content)+2], uint16(tagCount))
|
|
}
|
|
|
|
buf = buf[0 : 136+len(content)+2]
|
|
|
|
for _, tag := range evt.Tags {
|
|
if itemCount := len(tag); itemCount > MaxTagItemCount {
|
|
return nil, fmt.Errorf("can't encode a tag with so many items: %d, max is %d", itemCount, MaxTagItemCount)
|
|
} else {
|
|
buf = append(buf, uint8(itemCount))
|
|
}
|
|
for _, item := range tag {
|
|
itemb := []byte(item)
|
|
itemSize := len(itemb)
|
|
if itemSize > MaxTagItemSize {
|
|
return nil, fmt.Errorf("tag item is too large: %d, max is %d", itemSize, MaxTagItemSize)
|
|
}
|
|
buf = binary.BigEndian.AppendUint16(buf, uint16(itemSize))
|
|
buf = append(buf, itemb...)
|
|
buf = append(buf, 0)
|
|
}
|
|
}
|
|
return buf, nil
|
|
}
|