github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/protocol/gregor1/extras.go (about)

     1  package gregor1
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  	"strings"
     9  	"time"
    10  
    11  	"bytes"
    12  
    13  	"github.com/keybase/client/go/gregor"
    14  	"github.com/keybase/go-codec/codec"
    15  )
    16  
    17  func (u UID) Bytes() []byte     { return []byte(u) }
    18  func (u UID) String() string    { return hex.EncodeToString(u) }
    19  func (u UID) Eq(other UID) bool { return bytes.Equal(u.Bytes(), other.Bytes()) }
    20  func (u UID) IsNil() bool       { return len(u) == 0 }
    21  
    22  func UIDPtrEq(x, y *UID) bool {
    23  	if x != nil && y != nil {
    24  		return (*x).Eq(*y)
    25  	}
    26  	return (x == nil) && (y == nil)
    27  }
    28  
    29  func (d DeviceID) Bytes() []byte  { return []byte(d) }
    30  func (d DeviceID) String() string { return hex.EncodeToString(d) }
    31  func (d DeviceID) Eq(other DeviceID) bool {
    32  	return bytes.Equal(d.Bytes(), other.Bytes())
    33  }
    34  func (m MsgID) Bytes() []byte                 { return []byte(m) }
    35  func (m MsgID) String() string                { return hex.EncodeToString(m) }
    36  func (m MsgID) Eq(n MsgID) bool               { return m.String() == n.String() }
    37  func (s System) String() string               { return string(s) }
    38  func (c Category) String() string             { return string(c) }
    39  func (b Body) Bytes() []byte                  { return []byte(b) }
    40  func (c Category) Eq(c2 Category) bool        { return string(c) == string(c2) }
    41  func (c Category) HasPrefix(c2 Category) bool { return strings.HasPrefix(string(c), string(c2)) }
    42  
    43  func (t TimeOrOffset) Time() *time.Time {
    44  	if t.Time_.IsZero() {
    45  		return nil
    46  	}
    47  	ret := FromTime(t.Time_)
    48  	return &ret
    49  }
    50  func (t TimeOrOffset) Offset() *time.Duration {
    51  	if t.Offset_ == 0 {
    52  		return nil
    53  	}
    54  	d := time.Duration(t.Offset_) * time.Millisecond
    55  	return &d
    56  }
    57  func (t TimeOrOffset) IsZero() bool {
    58  	return t.Time_.IsZero() && t.Offset_ == 0
    59  }
    60  
    61  func (t TimeOrOffset) Before(t2 time.Time) bool {
    62  	if t.Time() != nil {
    63  		return t.Time().Before(t2)
    64  	}
    65  	if t.Offset() != nil {
    66  		return time.Now().Add(*t.Offset()).Before(t2)
    67  	}
    68  	return false
    69  }
    70  
    71  func (s StateSyncMessage) Metadata() gregor.Metadata {
    72  	return s.Md_
    73  }
    74  
    75  func (m MsgRange) EndTime() gregor.TimeOrOffset {
    76  	return m.EndTime_
    77  }
    78  func (m MsgRange) Category() gregor.Category {
    79  	return m.Category_
    80  }
    81  func (m MsgRange) SkipMsgIDs() (res []gregor.MsgID) {
    82  	for _, s := range m.SkipMsgIDs_ {
    83  		res = append(res, s)
    84  	}
    85  	return res
    86  }
    87  
    88  func (d Dismissal) RangesToDismiss() []gregor.MsgRange {
    89  	var ret []gregor.MsgRange
    90  	for _, r := range d.Ranges_ {
    91  		ret = append(ret, r)
    92  	}
    93  	return ret
    94  }
    95  
    96  func (d Dismissal) MsgIDsToDismiss() []gregor.MsgID {
    97  	var ret []gregor.MsgID
    98  	for _, m := range d.MsgIDs_ {
    99  		ret = append(ret, m)
   100  	}
   101  	return ret
   102  }
   103  
   104  func (m Metadata) CTime() time.Time { return FromTime(m.Ctime_) }
   105  func (m Metadata) UID() gregor.UID {
   106  	if m.Uid_ == nil {
   107  		return nil
   108  	}
   109  	return m.Uid_
   110  }
   111  func (m Metadata) MsgID() gregor.MsgID {
   112  	if m.MsgID_ == nil {
   113  		return nil
   114  	}
   115  	return m.MsgID_
   116  }
   117  func (m Metadata) DeviceID() gregor.DeviceID {
   118  	if m.DeviceID_ == nil {
   119  		return nil
   120  	}
   121  	return m.DeviceID_
   122  }
   123  func (m Metadata) InBandMsgType() gregor.InBandMsgType { return gregor.InBandMsgType(m.InBandMsgType_) }
   124  
   125  func (m Metadata) String() string {
   126  	return fmt.Sprintf("[ CTime: %s Type: %d ID: %s UID: %s ]", m.CTime(),
   127  		m.InBandMsgType(), m.MsgID(), m.UID())
   128  }
   129  
   130  func (i ItemAndMetadata) Metadata() gregor.Metadata {
   131  	if i.Md_ == nil {
   132  		return nil
   133  	}
   134  	return i.Md_
   135  }
   136  func (i ItemAndMetadata) Body() gregor.Body {
   137  	if i.Item_.Body_ == nil {
   138  		return nil
   139  	}
   140  	return i.Item_.Body_
   141  }
   142  func (i ItemAndMetadata) Category() gregor.Category {
   143  	if i.Item_.Category_ == "" {
   144  		return nil
   145  	}
   146  	return i.Item_.Category_
   147  }
   148  func (i ItemAndMetadata) DTime() gregor.TimeOrOffset {
   149  	var unset TimeOrOffset
   150  	if i.Item_.Dtime_ == unset {
   151  		return nil
   152  	}
   153  	return i.Item_.Dtime_
   154  }
   155  func (i ItemAndMetadata) RemindTimes() []gregor.TimeOrOffset {
   156  	var ret []gregor.TimeOrOffset
   157  	for _, t := range i.Item_.RemindTimes_ {
   158  		ret = append(ret, t)
   159  	}
   160  	return ret
   161  }
   162  
   163  func (i ItemAndMetadata) String() string {
   164  	rts := "[ "
   165  	for _, rt := range i.RemindTimes() {
   166  		rts += fmt.Sprintf("[%s,%s]", rt.Time(), rt.Offset())
   167  	}
   168  	rts += "]"
   169  	return fmt.Sprintf("MD: %s Cat: %s DTime: %s RTs: %s Body: %s", i.Metadata(),
   170  		i.Category(), i.DTime(), rts, i.Body())
   171  }
   172  
   173  func (s StateUpdateMessage) Metadata() gregor.Metadata { return s.Md_ }
   174  func (s StateUpdateMessage) Creation() gregor.Item {
   175  	if s.Creation_ == nil {
   176  		return nil
   177  	}
   178  	return ItemAndMetadata{Md_: &s.Md_, Item_: s.Creation_}
   179  }
   180  func (s StateUpdateMessage) Dismissal() gregor.Dismissal {
   181  	if s.Dismissal_ == nil {
   182  		return nil
   183  	}
   184  	return s.Dismissal_
   185  }
   186  
   187  func (i InBandMessage) Merge(i2 gregor.InBandMessage) (res gregor.InBandMessage, err error) {
   188  	t2, ok := i2.(InBandMessage)
   189  	if !ok {
   190  		return res, fmt.Errorf("bad merge; wrong type: %T", i2)
   191  	}
   192  	if i.StateSync_ != nil || t2.StateSync_ != nil {
   193  		return res, errors.New("Cannot merge sync messages")
   194  	}
   195  	st, err := i.StateUpdate_.Merge(t2.StateUpdate_)
   196  	if err != nil {
   197  		return res, err
   198  	}
   199  	return InBandMessage{StateUpdate_: &st}, nil
   200  }
   201  
   202  func (s StateUpdateMessage) Merge(s2 *StateUpdateMessage) (res StateUpdateMessage, err error) {
   203  	if s.Creation_ != nil && s2.Creation_ != nil {
   204  		return res, errors.New("cannot merge two creation messages")
   205  	}
   206  	res.Md_ = s.Md_
   207  	res.Creation_ = s.Creation_
   208  	if res.Creation_ == nil {
   209  		res.Creation_ = s2.Creation_
   210  	}
   211  	res.Dismissal_ = s.Dismissal_
   212  	if res.Dismissal_ == nil {
   213  		res.Dismissal_ = s2.Dismissal_
   214  	} else if res.Dismissal_ != nil && s2.Dismissal_ != nil {
   215  		res.Dismissal_.MsgIDs_ = append(res.Dismissal_.MsgIDs_, s2.Dismissal_.MsgIDs_...)
   216  		res.Dismissal_.Ranges_ = append(res.Dismissal_.Ranges_, s2.Dismissal_.Ranges_...)
   217  	}
   218  	return res, nil
   219  }
   220  
   221  func (i InBandMessage) Metadata() gregor.Metadata {
   222  	if i.StateUpdate_ != nil {
   223  		return i.StateUpdate_.Md_
   224  	}
   225  	if i.StateSync_ != nil {
   226  		return i.StateSync_.Md_
   227  	}
   228  	return nil
   229  }
   230  
   231  func (i InBandMessage) ToStateSyncMessage() gregor.StateSyncMessage {
   232  	if i.StateSync_ == nil {
   233  		return nil
   234  	}
   235  	return i.StateSync_
   236  }
   237  
   238  func (i InBandMessage) ToStateUpdateMessage() gregor.StateUpdateMessage {
   239  	if i.StateUpdate_ == nil {
   240  		return nil
   241  	}
   242  	return i.StateUpdate_
   243  }
   244  
   245  func (o OutOfBandMessage) Body() gregor.Body {
   246  	if o.Body_ == nil {
   247  		return nil
   248  	}
   249  	return o.Body_
   250  }
   251  func (o OutOfBandMessage) System() gregor.System {
   252  	if o.System_ == "" {
   253  		return nil
   254  	}
   255  	return o.System_
   256  }
   257  func (o OutOfBandMessage) UID() gregor.UID {
   258  	if o.Uid_ == nil {
   259  		return nil
   260  	}
   261  	return o.Uid_
   262  }
   263  
   264  func (m Message) ToInBandMessage() gregor.InBandMessage {
   265  	if m.Ibm_ == nil {
   266  		return nil
   267  	}
   268  	return *m.Ibm_
   269  }
   270  
   271  func (m Message) ToOutOfBandMessage() gregor.OutOfBandMessage {
   272  	if m.Oobm_ == nil {
   273  		return nil
   274  	}
   275  	return *m.Oobm_
   276  }
   277  
   278  func (m Message) Marshal() ([]byte, error) {
   279  	var b []byte
   280  	err := codec.NewEncoderBytes(&b, &codec.MsgpackHandle{WriteExt: true}).Encode(m)
   281  	return b, err
   282  }
   283  
   284  func (m *Message) SetCTime(ctime time.Time) {
   285  	if m.Ibm_ != nil && m.Ibm_.StateUpdate_ != nil {
   286  		m.Ibm_.StateUpdate_.Md_.Ctime_ = ToTime(ctime)
   287  	}
   288  }
   289  
   290  func (m *Message) SetUID(uid UID) error {
   291  	if m.Ibm_ != nil {
   292  		if m.Ibm_.StateUpdate_ != nil {
   293  			m.Ibm_.StateUpdate_.Md_.Uid_ = uid
   294  			return nil
   295  		}
   296  		if m.Ibm_.StateSync_ != nil {
   297  			m.Ibm_.StateSync_.Md_.Uid_ = uid
   298  			return nil
   299  		}
   300  		return errors.New("unable to set uid on inband message (no StatUpdate or StateSync)")
   301  	}
   302  	if m.Oobm_ != nil {
   303  		m.Oobm_.Uid_ = uid
   304  		return nil
   305  	}
   306  
   307  	return errors.New("unable to set uid (no inband or out-of-band message)")
   308  }
   309  
   310  func (r Reminder) Item() gregor.Item     { return r.Item_ }
   311  func (r Reminder) RemindTime() time.Time { return FromTime(r.RemindTime_) }
   312  func (r Reminder) Seqno() int            { return r.Seqno_ }
   313  
   314  func (r ReminderID) UID() gregor.UID     { return r.Uid_ }
   315  func (r ReminderID) MsgID() gregor.MsgID { return r.MsgID_ }
   316  func (r ReminderID) Seqno() int          { return r.Seqno_ }
   317  
   318  func (s State) Size() int {
   319  	return len(s.Items_)
   320  }
   321  
   322  func (s State) Items() ([]gregor.Item, error) {
   323  	ret := make([]gregor.Item, 0, len(s.Items_))
   324  	for _, i := range s.Items_ {
   325  		ret = append(ret, i)
   326  	}
   327  	return ret, nil
   328  }
   329  
   330  func (s State) GetItem(msgID gregor.MsgID) (gregor.Item, bool) {
   331  	for _, i := range s.Items_ {
   332  		if i.Metadata().MsgID().String() == msgID.String() {
   333  			return i, true
   334  		}
   335  	}
   336  	return nil, false
   337  }
   338  
   339  func (s State) Marshal() ([]byte, error) {
   340  	var b []byte
   341  	err := codec.NewEncoderBytes(&b, &codec.MsgpackHandle{WriteExt: true}).Encode(s)
   342  	return b, err
   343  }
   344  
   345  func (s State) Hash() ([]byte, error) {
   346  	b, err := s.Marshal()
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  
   351  	sum := sha256.Sum256(b)
   352  	return sum[:], nil
   353  }
   354  
   355  func (s State) Export() (gregor.ProtocolState, error) {
   356  	return s, nil
   357  }
   358  
   359  func (s State) ProtocolName() string {
   360  	return "gregor.1"
   361  }
   362  
   363  func (i ItemAndMetadata) InCategory(c Category) bool {
   364  	return i.Item_.Category_.Eq(c)
   365  }
   366  
   367  func (i ItemAndMetadata) HasCategoryPrefix(c Category) bool {
   368  	return i.Item_.Category_.HasPrefix(c)
   369  }
   370  
   371  func (s State) ItemsInCategory(gc gregor.Category) ([]gregor.Item, error) {
   372  	var ret []gregor.Item
   373  	c := Category(gc.String())
   374  	for _, i := range s.Items_ {
   375  		if i.InCategory(c) {
   376  			ret = append(ret, i)
   377  		}
   378  	}
   379  	return ret, nil
   380  }
   381  
   382  func (s State) ItemsWithCategoryPrefix(gc gregor.Category) ([]gregor.Item, error) {
   383  	var ret []gregor.Item
   384  	c := Category(gc.String())
   385  	for _, i := range s.Items_ {
   386  		if i.HasCategoryPrefix(c) {
   387  			ret = append(ret, i)
   388  		}
   389  	}
   390  	return ret, nil
   391  }
   392  
   393  func FromTime(t Time) time.Time {
   394  	if t == 0 {
   395  		return time.Time{}
   396  	}
   397  	return time.Unix(0, int64(t)*1000000)
   398  }
   399  
   400  func (t Time) Time() time.Time {
   401  	return FromTime(t)
   402  }
   403  
   404  func (t Time) UnixSeconds() int64 {
   405  	return t.Time().Unix()
   406  }
   407  
   408  func (t Time) UnixMilliseconds() int64 {
   409  	return t.Time().UnixNano() / 1e6
   410  }
   411  
   412  func (t Time) UnixMicroseconds() int64 {
   413  	return t.Time().UnixNano() / 1e3
   414  }
   415  
   416  // copied from keybase/client/go/protocol/extras.go. Consider eventually a
   417  // refactor to allow this code to be shared.
   418  func ToTime(t time.Time) Time {
   419  	// the result of calling UnixNano on the zero Time is undefined.
   420  	// https://golang.org/pkg/time/#Time.UnixNano
   421  	if t.IsZero() {
   422  		return 0
   423  	}
   424  	return Time(t.UnixNano() / 1000000)
   425  }
   426  
   427  func TimeFromSeconds(seconds int64) Time {
   428  	return Time(seconds * 1000)
   429  }
   430  
   431  func TimeFromMilliseconds(ms int64) Time {
   432  	return Time(ms)
   433  }
   434  
   435  func (t Time) IsZero() bool        { return t == 0 }
   436  func (t Time) After(t2 Time) bool  { return t > t2 }
   437  func (t Time) Before(t2 Time) bool { return t < t2 }
   438  
   439  func FormatTime(t Time) string {
   440  	layout := "2006-01-02 15:04:05 MST"
   441  	return FromTime(t).Format(layout)
   442  }
   443  
   444  func ToDurationMsec(d time.Duration) DurationMsec {
   445  	return DurationMsec(d / time.Millisecond)
   446  }
   447  
   448  func (d DurationMsec) ToDuration() time.Duration {
   449  	return time.Duration(d) * time.Millisecond
   450  }
   451  
   452  func ToDurationSec(d time.Duration) DurationSec {
   453  	return DurationSec(d / time.Second)
   454  }
   455  
   456  func (d DurationSec) ToDuration() time.Duration {
   457  	return time.Duration(d) * time.Second
   458  }
   459  
   460  // DeviceID returns the deviceID in a SyncArc, or interface nil
   461  // (and not gregor1.DeviceID(nil)) if not was specified.
   462  func (s SyncArg) DeviceID() gregor.DeviceID {
   463  	if s.Deviceid == nil {
   464  		return nil
   465  	}
   466  	return s.Deviceid
   467  }
   468  
   469  // UID returns the UID in a SyncArc, or interface nil
   470  // (and not gregor1.UID(nil)) if not was specified.
   471  func (s SyncArg) UID() gregor.UID {
   472  	if s.Uid == nil {
   473  		return nil
   474  	}
   475  	return s.Uid
   476  }
   477  
   478  func (s SyncArg) CTime() time.Time {
   479  	return FromTime(s.Ctime)
   480  }
   481  
   482  func (r ReminderSet) Reminders() []gregor.Reminder {
   483  	var out []gregor.Reminder
   484  	for _, reminder := range r.Reminders_ {
   485  		out = append(out, reminder)
   486  	}
   487  	return out
   488  }
   489  
   490  func (r ReminderSet) MoreRemindersReady() bool { return r.MoreRemindersReady_ }
   491  
   492  func UIDListContains(list []UID, x UID) bool {
   493  	for _, y := range list {
   494  		if x.String() == y.String() {
   495  			return true
   496  		}
   497  	}
   498  	return false
   499  }
   500  
   501  // Merge two lists of UIDs. Duplicates will be dropped. Not stably ordered.
   502  func UIDListMerge(list1 []UID, list2 []UID) []UID {
   503  	m := make(map[string]UID)
   504  	for _, uid := range list1 {
   505  		m[uid.String()] = uid
   506  	}
   507  	for _, uid := range list2 {
   508  		m[uid.String()] = uid
   509  	}
   510  	res := make([]UID, 0)
   511  	for _, uid := range m {
   512  		res = append(res, uid)
   513  	}
   514  	return res
   515  }
   516  
   517  var _ gregor.UID = UID{}
   518  var _ gregor.MsgID = MsgID{}
   519  var _ gregor.DeviceID = DeviceID{}
   520  var _ gregor.System = System("")
   521  var _ gregor.Body = Body{}
   522  var _ gregor.Category = Category("")
   523  var _ gregor.TimeOrOffset = TimeOrOffset{}
   524  var _ gregor.Metadata = Metadata{}
   525  var _ gregor.StateSyncMessage = StateSyncMessage{}
   526  var _ gregor.MsgRange = MsgRange{}
   527  var _ gregor.Dismissal = Dismissal{}
   528  var _ gregor.Item = ItemAndMetadata{}
   529  var _ gregor.Reminder = Reminder{}
   530  var _ gregor.StateUpdateMessage = StateUpdateMessage{}
   531  var _ gregor.InBandMessage = InBandMessage{}
   532  var _ gregor.OutOfBandMessage = OutOfBandMessage{}
   533  var _ gregor.Message = Message{}
   534  var _ gregor.State = State{}
   535  var _ gregor.ReminderID = ReminderID{}
   536  var _ gregor.ReminderSet = ReminderSet{}