fork of indigo with slightly nicer lexgen
at main 3.4 kB view raw
1package data 2 3import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 9 "github.com/ipfs/go-cid" 10 cbg "github.com/whyrusleeping/cbor-gen" 11) 12 13// Represents the "blob" type from the atproto data model. 14// 15// This struct does not get marshaled/unmarshaled directly in to JSON or CBOR; see the BlobSchema and LegacyBlobSchema structs. This is the type that should be included in golang struct definitions. 16// 17// When representing a "legacy" blob (no size field, string CID), size == -1. 18type Blob struct { 19 Ref CIDLink 20 MimeType string 21 Size int64 22} 23 24type LegacyBlobSchema struct { 25 Cid string `json:"cid" cborgen:"cid"` 26 MimeType string `json:"mimeType" cborgen:"mimeType"` 27} 28 29type BlobSchema struct { 30 LexiconTypeID string `json:"$type" cborgen:"$type,const=blob"` 31 Ref CIDLink `json:"ref" cborgen:"ref"` 32 MimeType string `json:"mimeType" cborgen:"mimeType"` 33 Size int64 `json:"size" cborgen:"size"` 34} 35 36func (b Blob) MarshalJSON() ([]byte, error) { 37 if b.Size < 0 { 38 lb := LegacyBlobSchema{ 39 Cid: b.Ref.String(), 40 MimeType: b.MimeType, 41 } 42 return json.Marshal(lb) 43 } else { 44 nb := BlobSchema{ 45 LexiconTypeID: "blob", 46 Ref: b.Ref, 47 MimeType: b.MimeType, 48 Size: b.Size, 49 } 50 return json.Marshal(nb) 51 } 52} 53 54func (b *Blob) UnmarshalJSON(raw []byte) error { 55 typ, err := ExtractTypeJSON(raw) 56 if err != nil { 57 return fmt.Errorf("parsing blob type: %v", err) 58 } 59 60 if typ == "blob" { 61 var bs BlobSchema 62 err := json.Unmarshal(raw, &bs) 63 if err != nil { 64 return fmt.Errorf("parsing blob JSON: %v", err) 65 } 66 b.Ref = bs.Ref 67 b.MimeType = bs.MimeType 68 b.Size = bs.Size 69 if bs.Size < 0 { 70 return fmt.Errorf("parsing blob: negative size: %d", bs.Size) 71 } 72 } else { 73 var legacy LegacyBlobSchema 74 err := json.Unmarshal(raw, &legacy) 75 if err != nil { 76 return fmt.Errorf("parsing legacy blob: %v", err) 77 } 78 refCid, err := cid.Decode(legacy.Cid) 79 if err != nil { 80 return fmt.Errorf("parsing CID in legacy blob: %v", err) 81 } 82 b.Ref = CIDLink(refCid) 83 b.MimeType = legacy.MimeType 84 b.Size = -1 85 } 86 return nil 87} 88 89func (b *Blob) MarshalCBOR(w io.Writer) error { 90 if b == nil { 91 _, err := w.Write(cbg.CborNull) 92 return err 93 } 94 if b.Size < 0 { 95 lb := LegacyBlobSchema{ 96 Cid: b.Ref.String(), 97 MimeType: b.MimeType, 98 } 99 return lb.MarshalCBOR(w) 100 } else { 101 bs := BlobSchema{ 102 LexiconTypeID: "blob", 103 Ref: b.Ref, 104 MimeType: b.MimeType, 105 Size: b.Size, 106 } 107 return bs.MarshalCBOR(w) 108 } 109} 110 111func (lb *Blob) UnmarshalCBOR(r io.Reader) error { 112 typ, b, err := ExtractTypeCBORReader(r) 113 if err != nil { 114 return fmt.Errorf("parsing $blob CBOR type: %w", err) 115 } 116 117 *lb = Blob{} 118 if typ == "blob" { 119 var bs BlobSchema 120 err := bs.UnmarshalCBOR(bytes.NewReader(b)) 121 if err != nil { 122 return fmt.Errorf("parsing $blob CBOR: %v", err) 123 } 124 lb.Ref = bs.Ref 125 lb.MimeType = bs.MimeType 126 lb.Size = bs.Size 127 if bs.Size < 0 { 128 return fmt.Errorf("parsing $blob CBOR: negative size: %d", bs.Size) 129 } 130 } else { 131 legacy := LegacyBlobSchema{} 132 err := legacy.UnmarshalCBOR(bytes.NewReader(b)) 133 if err != nil { 134 return fmt.Errorf("parsing legacy blob CBOR: %v", err) 135 } 136 refCid, err := cid.Decode(legacy.Cid) 137 if err != nil { 138 return fmt.Errorf("parsing CID in legacy blob CBOR: %v", err) 139 } 140 lb.Ref = CIDLink(refCid) 141 lb.MimeType = legacy.MimeType 142 lb.Size = -1 143 } 144 145 return nil 146}