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  }