169 lines
4.2 KiB
Go
169 lines
4.2 KiB
Go
package oid
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/sha256"
|
|
"fmt"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs"
|
|
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
|
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
|
"github.com/mr-tron/base58"
|
|
)
|
|
|
|
// ID represents FrostFS object identifier in a container.
|
|
//
|
|
// ID is mutually compatible with git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs.ObjectID
|
|
// message. See ReadFromV2 / WriteToV2 methods.
|
|
//
|
|
// Instances can be created using built-in var declaration.
|
|
//
|
|
// Note that direct typecast is not safe and may result in loss of compatibility:
|
|
//
|
|
// _ = ID([32]byte{}) // not recommended
|
|
type ID [sha256.Size]byte
|
|
|
|
// ReadFromV2 reads ID from the refs.ObjectID message. Returns an error if
|
|
// the message is malformed according to the FrostFS API V2 protocol.
|
|
//
|
|
// See also WriteToV2.
|
|
func (id *ID) ReadFromV2(m refs.ObjectID) error {
|
|
return id.Decode(m.GetValue())
|
|
}
|
|
|
|
// WriteToV2 writes ID to the refs.ObjectID message.
|
|
// The message must not be nil.
|
|
//
|
|
// See also ReadFromV2.
|
|
func (id ID) WriteToV2(m *refs.ObjectID) {
|
|
m.SetValue(id[:])
|
|
}
|
|
|
|
// Encode encodes ID into 32 bytes of dst. Panics if
|
|
// dst length is less than 32.
|
|
//
|
|
// Zero ID is all zeros.
|
|
//
|
|
// See also Decode.
|
|
func (id ID) Encode(dst []byte) {
|
|
if l := len(dst); l < sha256.Size {
|
|
panic(fmt.Sprintf("destination length is less than %d bytes: %d", sha256.Size, l))
|
|
}
|
|
|
|
copy(dst, id[:])
|
|
}
|
|
|
|
// Decode decodes src bytes into ID.
|
|
//
|
|
// Decode expects that src has 32 bytes length. If the input is malformed,
|
|
// Decode returns an error describing format violation. In this case ID
|
|
// remains unchanged.
|
|
//
|
|
// Decode doesn't mutate src.
|
|
//
|
|
// See also Encode.
|
|
func (id *ID) Decode(src []byte) error {
|
|
if len(src) != 32 {
|
|
return fmt.Errorf("invalid length %d", len(src))
|
|
}
|
|
|
|
copy(id[:], src)
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetSHA256 sets object identifier value to SHA256 checksum.
|
|
func (id *ID) SetSHA256(v [sha256.Size]byte) {
|
|
copy(id[:], v[:])
|
|
}
|
|
|
|
// Equals defines a comparison relation between two ID instances.
|
|
//
|
|
// Note that comparison using '==' operator is not recommended since it MAY result
|
|
// in loss of compatibility.
|
|
func (id ID) Equals(id2 ID) bool {
|
|
return id == id2
|
|
}
|
|
|
|
// EncodeToString encodes ID into FrostFS API protocol string.
|
|
//
|
|
// Zero ID is base58 encoding of 32 zeros.
|
|
//
|
|
// See also DecodeString.
|
|
func (id ID) EncodeToString() string {
|
|
return base58.Encode(id[:])
|
|
}
|
|
|
|
// DecodeString decodes string into ID according to FrostFS API protocol. Returns
|
|
// an error if s is malformed.
|
|
//
|
|
// See also DecodeString.
|
|
func (id *ID) DecodeString(s string) error {
|
|
data, err := base58.Decode(s)
|
|
if err != nil {
|
|
return fmt.Errorf("decode base58: %w", err)
|
|
}
|
|
|
|
return id.Decode(data)
|
|
}
|
|
|
|
// String implements fmt.Stringer.
|
|
//
|
|
// String is designed to be human-readable, and its format MAY differ between
|
|
// SDK versions. String MAY return same result as EncodeToString. String MUST NOT
|
|
// be used to encode ID into FrostFS protocol string.
|
|
func (id ID) String() string {
|
|
return id.EncodeToString()
|
|
}
|
|
|
|
// CalculateIDSignature signs object id with provided key.
|
|
func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (frostfscrypto.Signature, error) {
|
|
data, err := id.Marshal()
|
|
if err != nil {
|
|
return frostfscrypto.Signature{}, fmt.Errorf("marshal ID: %w", err)
|
|
}
|
|
|
|
var sig frostfscrypto.Signature
|
|
|
|
return sig, sig.Calculate(frostfsecdsa.Signer(key), data)
|
|
}
|
|
|
|
// Marshal marshals ID into a protobuf binary form.
|
|
func (id ID) Marshal() ([]byte, error) {
|
|
var v2 refs.ObjectID
|
|
v2.SetValue(id[:])
|
|
|
|
return v2.StableMarshal(nil), nil
|
|
}
|
|
|
|
// Unmarshal unmarshals protobuf binary representation of ID.
|
|
func (id *ID) Unmarshal(data []byte) error {
|
|
var v2 refs.ObjectID
|
|
if err := v2.Unmarshal(data); err != nil {
|
|
return err
|
|
}
|
|
|
|
copy(id[:], v2.GetValue())
|
|
|
|
return nil
|
|
}
|
|
|
|
// MarshalJSON encodes ID to protobuf JSON format.
|
|
func (id ID) MarshalJSON() ([]byte, error) {
|
|
var v2 refs.ObjectID
|
|
v2.SetValue(id[:])
|
|
|
|
return v2.MarshalJSON()
|
|
}
|
|
|
|
// UnmarshalJSON decodes ID from protobuf JSON format.
|
|
func (id *ID) UnmarshalJSON(data []byte) error {
|
|
var v2 refs.ObjectID
|
|
if err := v2.UnmarshalJSON(data); err != nil {
|
|
return err
|
|
}
|
|
|
|
copy(id[:], v2.GetValue())
|
|
|
|
return nil
|
|
}
|