github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/kbfsmd/id.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package kbfsmd 6 7 import ( 8 "encoding" 9 "encoding/hex" 10 11 "github.com/keybase/client/go/kbfs/kbfscodec" 12 "github.com/keybase/client/go/kbfs/kbfshash" 13 "github.com/pkg/errors" 14 ) 15 16 // ID is the content-based ID for a metadata block. 17 type ID struct { 18 h kbfshash.Hash 19 } 20 21 var _ encoding.BinaryMarshaler = ID{} 22 var _ encoding.BinaryUnmarshaler = (*ID)(nil) 23 24 var _ encoding.TextMarshaler = ID{} 25 var _ encoding.TextUnmarshaler = (*ID)(nil) 26 27 // MakeID creates a new ID from the given RootMetadata object. 28 func MakeID(codec kbfscodec.Codec, md RootMetadata) (ID, error) { 29 // Make sure that the serialized metadata is set; otherwise we 30 // won't get the right ID. 31 if md.GetSerializedPrivateMetadata() == nil { 32 return ID{}, errors.WithStack(MissingDataError{md.TlfID()}) 33 } 34 35 buf, err := codec.Encode(md) 36 if err != nil { 37 return ID{}, err 38 } 39 40 h, err := kbfshash.DefaultHash(buf) 41 if err != nil { 42 return ID{}, err 43 } 44 45 return ID{h}, nil 46 } 47 48 // FakeID returns an ID derived from the given byte, suitable for 49 // testing. 50 func FakeID(b byte) ID { 51 dh := kbfshash.RawDefaultHash{b} 52 h, err := kbfshash.HashFromRaw(kbfshash.DefaultHashType, dh[:]) 53 if err != nil { 54 panic(err) 55 } 56 return ID{h} 57 } 58 59 // Bytes returns the bytes of the MDID. 60 func (id ID) Bytes() []byte { 61 return id.h.Bytes() 62 } 63 64 func (id ID) String() string { 65 return id.h.String() 66 } 67 68 // MarshalBinary implements the encoding.BinaryMarshaler interface for 69 // ID. Returns an error if the ID is invalid and not the zero 70 // ID. 71 func (id ID) MarshalBinary() (data []byte, err error) { 72 return id.h.MarshalBinary() 73 } 74 75 // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface 76 // for ID. Returns an error if the given byte array is non-empty and 77 // the ID is invalid. 78 func (id *ID) UnmarshalBinary(data []byte) error { 79 return id.h.UnmarshalBinary(data) 80 } 81 82 // MarshalText implements the encoding.TextMarshaler interface for ID. 83 func (id ID) MarshalText() ([]byte, error) { 84 bytes, err := id.MarshalBinary() 85 if err != nil { 86 return nil, err 87 } 88 return []byte(hex.EncodeToString(bytes)), nil 89 } 90 91 // UnmarshalText implements the encoding.TextUnmarshaler interface for 92 // ID. 93 func (id *ID) UnmarshalText(buf []byte) error { 94 s := string(buf) 95 bytes, err := hex.DecodeString(s) 96 if err != nil { 97 return errors.WithStack(InvalidIDError{s}) 98 } 99 return id.UnmarshalBinary(bytes) 100 } 101 102 // IsValid returns whether the ID is valid. 103 func (id ID) IsValid() bool { 104 return id.h.IsValid() 105 } 106 107 // ParseID parses a hex encoded ID. Returns ID{} and an InvalidIDError 108 // on failure. 109 func ParseID(s string) (ID, error) { 110 var id ID 111 err := id.UnmarshalText([]byte(s)) 112 if err != nil { 113 return ID{}, err 114 } 115 return id, nil 116 }