git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/object/id/address.go (about) 1 package oid 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" 9 cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" 10 ) 11 12 // Address represents global object identifier in FrostFS network. Each object 13 // belongs to exactly one container and is uniquely addressed within the container. 14 // 15 // Address is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs.Address 16 // message. See ReadFromV2 / WriteToV2 methods. 17 // 18 // Instances can be created using built-in var declaration. 19 type Address struct { 20 cnr cid.ID 21 22 obj ID 23 } 24 25 // ReadFromV2 reads Address from the refs.Address message. Returns an error if 26 // the message is malformed according to the FrostFS API V2 protocol. 27 // 28 // See also WriteToV2. 29 func (x *Address) ReadFromV2(m refs.Address) error { 30 cnr := m.GetContainerID() 31 if cnr == nil { 32 return errors.New("missing container ID") 33 } 34 35 obj := m.GetObjectID() 36 if obj == nil { 37 return errors.New("missing object ID") 38 } 39 40 err := x.cnr.ReadFromV2(*cnr) 41 if err != nil { 42 return fmt.Errorf("invalid container ID: %w", err) 43 } 44 45 err = x.obj.ReadFromV2(*obj) 46 if err != nil { 47 return fmt.Errorf("invalid object ID: %w", err) 48 } 49 50 return nil 51 } 52 53 // WriteToV2 writes Address to the refs.Address message. 54 // The message must not be nil. 55 // 56 // See also ReadFromV2. 57 func (x Address) WriteToV2(m *refs.Address) { 58 var obj refs.ObjectID 59 x.obj.WriteToV2(&obj) 60 61 var cnr refs.ContainerID 62 x.cnr.WriteToV2(&cnr) 63 64 m.SetObjectID(&obj) 65 m.SetContainerID(&cnr) 66 } 67 68 // MarshalJSON encodes Address into a JSON format of the FrostFS API protocol 69 // (Protocol Buffers JSON). 70 // 71 // See also UnmarshalJSON. 72 func (x Address) MarshalJSON() ([]byte, error) { 73 var m refs.Address 74 x.WriteToV2(&m) 75 76 return m.MarshalJSON() 77 } 78 79 // UnmarshalJSON decodes FrostFS API protocol JSON format into the Address 80 // (Protocol Buffers JSON). Returns an error describing a format violation. 81 // 82 // See also MarshalJSON. 83 func (x *Address) UnmarshalJSON(data []byte) error { 84 var m refs.Address 85 86 err := m.UnmarshalJSON(data) 87 if err != nil { 88 return err 89 } 90 91 return x.ReadFromV2(m) 92 } 93 94 // Container returns unique identifier of the FrostFS object container. 95 // 96 // Zero Address has zero container ID, which is incorrect according to FrostFS 97 // API protocol. 98 // 99 // See also SetContainer. 100 func (x Address) Container() cid.ID { 101 return x.cnr 102 } 103 104 // SetContainer sets unique identifier of the FrostFS object container. 105 // 106 // See also Container. 107 func (x *Address) SetContainer(id cid.ID) { 108 x.cnr = id 109 } 110 111 // Object returns unique identifier of the object in the container 112 // identified by Container(). 113 // 114 // Zero Address has zero object ID, which is incorrect according to FrostFS 115 // API protocol. 116 // 117 // See also SetObject. 118 func (x Address) Object() ID { 119 return x.obj 120 } 121 122 // SetObject sets unique identifier of the object in the container 123 // identified by Container(). 124 // 125 // See also Object. 126 func (x *Address) SetObject(id ID) { 127 x.obj = id 128 } 129 130 // delimiter of container and object IDs in Address protocol string. 131 const idDelimiter = "/" 132 133 // EncodeToString encodes Address into FrostFS API protocol string: concatenation 134 // of the string-encoded container and object IDs delimited by a slash. 135 // 136 // See also DecodeString. 137 func (x Address) EncodeToString() string { 138 return x.cnr.EncodeToString() + "/" + x.obj.EncodeToString() 139 } 140 141 // DecodeString decodes string into Address according to FrostFS API protocol. Returns 142 // an error if s is malformed. 143 // 144 // See also DecodeString. 145 func (x *Address) DecodeString(s string) error { 146 indDelimiter := strings.Index(s, idDelimiter) 147 if indDelimiter < 0 { 148 return errors.New("missing delimiter") 149 } 150 151 err := x.cnr.DecodeString(s[:indDelimiter]) 152 if err != nil { 153 return fmt.Errorf("decode container string: %w", err) 154 } 155 156 err = x.obj.DecodeString(s[indDelimiter+1:]) 157 if err != nil { 158 return fmt.Errorf("decode object string: %w", err) 159 } 160 161 return nil 162 } 163 164 // String implements fmt.Stringer. 165 // 166 // String is designed to be human-readable, and its format MAY differ between 167 // SDK versions. String MAY return same result as EncodeToString. String MUST NOT 168 // be used to encode Address into FrostFS protocol string. 169 func (x Address) String() string { 170 return x.EncodeToString() 171 } 172 173 // Equals defines a comparison relation between two Address's instances. 174 // 175 // Note that comparison using '==' operator is not recommended since it MAY result 176 // in loss of compatibility. 177 func (x Address) Equals(other Address) bool { 178 return x.obj.Equals(other.obj) && x.cnr.Equals(other.cnr) 179 }