github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/protocol/gregor1/factory.go (about) 1 package gregor1 2 3 import ( 4 "bytes" 5 "errors" 6 "sort" 7 "time" 8 9 "github.com/keybase/client/go/gregor" 10 "github.com/keybase/go-codec/codec" 11 ) 12 13 type ObjFactory struct{} 14 15 func (o ObjFactory) MakeUID(b []byte) (gregor.UID, error) { return UID(b), nil } 16 func (o ObjFactory) MakeMsgID(b []byte) (gregor.MsgID, error) { return MsgID(b), nil } 17 func (o ObjFactory) MakeDeviceID(b []byte) (gregor.DeviceID, error) { return DeviceID(b), nil } 18 func (o ObjFactory) MakeBody(b []byte) (gregor.Body, error) { return Body(b), nil } 19 func (o ObjFactory) MakeSystem(s string) (gregor.System, error) { return System(s), nil } 20 func (o ObjFactory) MakeCategory(s string) (gregor.Category, error) { return Category(s), nil } 21 22 func castUID(uid gregor.UID) (ret UID, err error) { 23 if uid == nil { 24 return 25 } 26 ret, ok := uid.(UID) 27 if !ok { 28 err = errors.New("bad UID; wrong type") 29 } 30 return 31 } 32 33 func castDeviceID(d gregor.DeviceID) (ret DeviceID, err error) { 34 if d == nil { 35 return 36 } 37 ret, ok := d.(DeviceID) 38 if !ok { 39 err = errors.New("bad Device ID; wrong type") 40 } 41 return 42 } 43 44 func castItem(i gregor.Item) (ret ItemAndMetadata, err error) { 45 ret, ok := i.(ItemAndMetadata) 46 if !ok { 47 err = errors.New("bad Item; wrong type") 48 } 49 return 50 } 51 52 func castInBandMessage(i gregor.InBandMessage) (ret InBandMessage, err error) { 53 ret, ok := i.(InBandMessage) 54 if !ok { 55 err = errors.New("bad InBandMessage; wrong type") 56 } 57 return 58 } 59 60 func timeToTimeOrOffset(timeIn *time.Time) (too TimeOrOffset) { 61 if timeIn != nil { 62 too.Time_ = ToTime(*timeIn) 63 } 64 return 65 } 66 67 func (o ObjFactory) makeMetadata(uid gregor.UID, msgid gregor.MsgID, devid gregor.DeviceID, ctime time.Time, i gregor.InBandMsgType) (Metadata, error) { 68 uid2, e := castUID(uid) 69 if e != nil { 70 return Metadata{}, e 71 } 72 devid2, e := castDeviceID(devid) 73 if e != nil { 74 return Metadata{}, e 75 } 76 77 return Metadata{ 78 Uid_: uid2, 79 MsgID_: MsgID(msgid.Bytes()), 80 Ctime_: ToTime(ctime), 81 DeviceID_: devid2, 82 InBandMsgType_: int(i), 83 }, nil 84 } 85 86 func (o ObjFactory) makeItem(c gregor.Category, d *time.Time, b gregor.Body) *Item { 87 return &Item{ 88 Dtime_: timeToTimeOrOffset(d), 89 Category_: Category(c.String()), 90 Body_: Body(b.Bytes()), 91 } 92 } 93 94 func (o ObjFactory) MakeItem(u gregor.UID, msgid gregor.MsgID, deviceid gregor.DeviceID, ctime time.Time, c gregor.Category, dtime *time.Time, body gregor.Body) (gregor.Item, error) { 95 md, err := o.makeMetadata(u, msgid, deviceid, ctime, gregor.InBandMsgTypeUpdate) 96 if err != nil { 97 return nil, err 98 } 99 return ItemAndMetadata{ 100 Md_: &md, 101 Item_: o.makeItem(c, dtime, body), 102 }, nil 103 } 104 105 func (o ObjFactory) MakeReminder(i gregor.Item, seqno int, t time.Time) (gregor.Reminder, error) { 106 it, ok := i.(ItemAndMetadata) 107 if !ok { 108 return nil, errors.New("item is not gregor1.ItemAndMetadata") 109 } 110 return Reminder{ 111 Item_: it, 112 Seqno_: seqno, 113 RemindTime_: ToTime(t), 114 }, nil 115 } 116 117 func (o ObjFactory) MakeDismissalByRange(uid gregor.UID, msgid gregor.MsgID, devid gregor.DeviceID, ctime time.Time, c gregor.Category, d time.Time, skipMsgIDs []gregor.MsgID) (gregor.InBandMessage, error) { 118 md, err := o.makeMetadata(uid, msgid, devid, ctime, gregor.InBandMsgTypeUpdate) 119 if err != nil { 120 return nil, err 121 } 122 var skips []MsgID 123 for _, s := range skipMsgIDs { 124 skips = append(skips, MsgID(s.Bytes())) 125 } 126 return InBandMessage{ 127 StateUpdate_: &StateUpdateMessage{ 128 Md_: md, 129 Dismissal_: &Dismissal{ 130 Ranges_: []MsgRange{{ 131 EndTime_: timeToTimeOrOffset(&d), 132 Category_: Category(c.String()), 133 SkipMsgIDs_: skips, 134 }}, 135 }, 136 }, 137 }, nil 138 } 139 140 func (o ObjFactory) MakeDismissalByIDs(uid gregor.UID, msgid gregor.MsgID, devid gregor.DeviceID, ctime time.Time, ids []gregor.MsgID) (gregor.InBandMessage, error) { 141 md, err := o.makeMetadata(uid, msgid, devid, ctime, gregor.InBandMsgTypeUpdate) 142 if err != nil { 143 return nil, err 144 } 145 ourIds := make([]MsgID, len(ids)) 146 for i, id := range ids { 147 ourIds[i] = MsgID(id.Bytes()) 148 } 149 return InBandMessage{ 150 StateUpdate_: &StateUpdateMessage{ 151 Md_: md, 152 Dismissal_: &Dismissal{ 153 MsgIDs_: ourIds, 154 }, 155 }, 156 }, nil 157 } 158 159 func (o ObjFactory) MakeStateSyncMessage(uid gregor.UID, msgid gregor.MsgID, devid gregor.DeviceID, ctime time.Time) (gregor.InBandMessage, error) { 160 md, err := o.makeMetadata(uid, msgid, devid, ctime, gregor.InBandMsgTypeUpdate) 161 if err != nil { 162 return nil, err 163 } 164 return InBandMessage{ 165 StateSync_: &StateSyncMessage{ 166 Md_: md, 167 }, 168 }, nil 169 } 170 171 type itemSlice []ItemAndMetadata 172 173 func (its itemSlice) Len() int { return len(its) } 174 func (its itemSlice) Swap(i, j int) { its[i], its[j] = its[j], its[i] } 175 176 // Less returns true if i's ctime is before j's, or if they're equal and 177 // i's MsgID is lexicographically before j's. 178 func (its itemSlice) Less(i, j int) bool { 179 mI, mJ := its[i].Metadata(), its[j].Metadata() 180 if mI != nil && mJ != nil { 181 if mI.CTime().Equal(mJ.CTime()) { 182 if mI.MsgID() != nil && mJ.MsgID() != nil { 183 return bytes.Compare(mI.MsgID().Bytes(), mJ.MsgID().Bytes()) < 0 184 } else { 185 return mI.MsgID() == nil 186 } 187 } 188 return mI.CTime().Before(mJ.CTime()) 189 } 190 return mI == nil 191 } 192 193 func (o ObjFactory) MakeState(items []gregor.Item) (gregor.State, error) { 194 ourItems := make(itemSlice, 0, len(items)) 195 for _, item := range items { 196 ourItem, err := castItem(item) 197 if err != nil { 198 return nil, err 199 } 200 ourItems = append(ourItems, ourItem) 201 } 202 sort.Sort(ourItems) 203 return State{Items_: ourItems}, nil 204 } 205 206 func (o ObjFactory) MakeStateWithLookupTable(items []gregor.Item, table map[string]gregor.Item) (gregor.State, error) { 207 return o.MakeState(items) 208 } 209 210 func (o ObjFactory) MakeMetadata(uid gregor.UID, msgid gregor.MsgID, devid gregor.DeviceID, ctime time.Time, i gregor.InBandMsgType) (gregor.Metadata, error) { 211 return o.makeMetadata(uid, msgid, devid, ctime, gregor.InBandMsgTypeUpdate) 212 } 213 214 func (o ObjFactory) MakeInBandMessageFromItem(i gregor.Item) (gregor.InBandMessage, error) { 215 ourItem, err := castItem(i) 216 if err != nil { 217 return nil, err 218 } 219 return InBandMessage{ 220 StateUpdate_: &StateUpdateMessage{ 221 Md_: *ourItem.Md_, 222 Creation_: ourItem.Item_, 223 }, 224 }, nil 225 } 226 227 func (o ObjFactory) MakeMessageFromInBandMessage(i gregor.InBandMessage) (gregor.Message, error) { 228 ourInBandMessage, err := castInBandMessage(i) 229 if err != nil { 230 return nil, err 231 } 232 return Message{ 233 Ibm_: &ourInBandMessage, 234 }, nil 235 } 236 237 func (o ObjFactory) UnmarshalState(b []byte) (gregor.State, error) { 238 var state State 239 err := codec.NewDecoderBytes(b, &codec.MsgpackHandle{WriteExt: true}). 240 Decode(&state) 241 if err != nil { 242 return nil, err 243 } 244 245 return state, nil 246 } 247 248 func (o ObjFactory) UnmarshalMessage(b []byte) (gregor.Message, error) { 249 var message Message 250 err := codec.NewDecoderBytes(b, &codec.MsgpackHandle{WriteExt: true}).Decode(&message) 251 if err != nil { 252 return nil, err 253 } 254 return message, nil 255 } 256 257 func (o ObjFactory) MakeTimeOrOffsetFromTime(t time.Time) (gregor.TimeOrOffset, error) { 258 return timeToTimeOrOffset(&t), nil 259 } 260 261 func (o ObjFactory) MakeTimeOrOffsetFromOffset(d time.Duration) (gregor.TimeOrOffset, error) { 262 return TimeOrOffset{Offset_: DurationMsec(d / time.Millisecond)}, nil 263 } 264 265 func (o ObjFactory) ExportTimeOrOffset(t gregor.TimeOrOffset) TimeOrOffset { 266 if t.Time() != nil { 267 return TimeOrOffset{ 268 Time_: ToTime(*t.Time()), 269 } 270 } 271 if t.Offset() != nil { 272 return TimeOrOffset{ 273 Offset_: DurationMsec(*t.Offset() / time.Millisecond), 274 } 275 } 276 return TimeOrOffset{} 277 } 278 279 func (o ObjFactory) ExportTimeOrOffsets(ts []gregor.TimeOrOffset) (res []TimeOrOffset) { 280 for _, t := range ts { 281 res = append(res, o.ExportTimeOrOffset(t)) 282 } 283 return res 284 } 285 286 func (o ObjFactory) MakeReminderID(u gregor.UID, msgid gregor.MsgID, seqno int) (gregor.ReminderID, error) { 287 return ReminderID{Uid_: u.Bytes(), MsgID_: msgid.Bytes(), Seqno_: seqno}, nil 288 } 289 290 func (o ObjFactory) MakeReminderSetFromReminders(reminders []gregor.Reminder, moreRemindersReady bool) (gregor.ReminderSet, error) { 291 ret := ReminderSet{MoreRemindersReady_: moreRemindersReady} 292 for _, reminder := range reminders { 293 if r, ok := reminder.(Reminder); ok { 294 ret.Reminders_ = append(ret.Reminders_, r) 295 } else { 296 return nil, errors.New("Can't upcast reminder") 297 } 298 } 299 return ret, nil 300 } 301 302 func (o ObjFactory) MakeOutOfBandMessage(uid gregor.UID, system gregor.System, body gregor.Body) gregor.Message { 303 return Message{ 304 Oobm_: &OutOfBandMessage{Uid_: uid.Bytes(), System_: System(system.String()), Body_: body.Bytes()}, 305 } 306 } 307 308 var _ gregor.ObjFactory = ObjFactory{}