Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add some helpers for creating new CIDs #52

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cid.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ func NewCidV1(codecType uint64, mhash mh.Multihash) *Cid {
}

// NewPrefixV0 returns a CIDv0 prefix with the specified multihash type.
//
// Deprecated: Please use the Format constructors (e.g., NewFormat).
func NewPrefixV0(mhType uint64) Prefix {
return Prefix{
MhType: mhType,
Expand All @@ -156,6 +158,8 @@ func NewPrefixV0(mhType uint64) Prefix {

// NewPrefixV1 returns a CIDv1 prefix with the specified codec and multihash
// type.
//
// Deprecated: Please use the Format constructors (e.g., NewFormat).
func NewPrefixV1(codecType uint64, mhType uint64) Prefix {
return Prefix{
MhType: mhType,
Expand Down
144 changes: 144 additions & 0 deletions format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package cid

import (
"fmt"

mh "github.com/multiformats/go-multihash"
)

// TODO: Move these to the correct go-ipld-* crates?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(discuss)


// DagProtobufV0Format is the default CID construction for DagProtobuf (CID V0)
// nodes.
var DagProtobufV0Format = Format{
version: 0,
codec: DagProtobuf,
mhLength: -1,
mhType: mh.SHA2_256,
inlineMax: -1,
}

// DagProtobufV1Format is the default CID construction for DagProtobuf (CID V1)
// nodes.
var DagProtobufV1Format = Format{
version: 1,
codec: DagProtobuf,
mhLength: -1,
mhType: mh.SHA2_256,
inlineMax: -1,
}

// RawFormat is the default CID construction for Raw IPLD nodes.
var RawFormat = Format{
version: 1,
codec: Raw,
mhType: mh.SHA2_256,
mhLength: -1,
inlineMax: -1,
}

// DagCBORFormat is the default CID construction for CBOR IPLD nodes.
var DagCBORFormat = Format{
version: 1,
codec: DagCBOR,
mhType: mh.SHA2_256,
mhLength: -1,
inlineMax: -1,
}

// Format represents a CID format.
type Format struct {
// CID spec
codec uint64
version uint64

// multhash spec
mhType uint64
mhLength int

// inline when the data is at most inlineMax in length
inlineMax int
}

// TODO: detect bad formats? Probably not worth it. We catch them on Sum anyways.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO


// With extends the format with the given options, returning a new format.
func (f Format) With(opts ...FormatOption) Format {
for _, opt := range opts {
opt(&f)
}
return f
}

// Sum constructs a CID for the given data. It *does not* check any properties
// of the data.
func (f *Format) Sum(data []byte) (*Cid, error) {
mhType := f.mhType
mhLen := f.mhLength
if len(data) <= f.inlineMax {
mhType = mh.ID
mhLen = -1
}

hash, err := mh.Sum(data, mhType, mhLen)
if err != nil {
return nil, err
}

switch f.version {
case 0:
if f.inlineMax != 0 {
return nil, fmt.Errorf("cannot inline with V0 CIDs")
}
if f.mhType != mh.SHA2_256 || (f.mhLength != -1 && f.mhLength != 256) {
return nil, fmt.Errorf("CIDv0 only supports 256bit SHA2_256 hashes")
}
return NewCidV0(hash), nil
case 1:
return NewCidV1(f.codec, hash), nil
default:
return nil, fmt.Errorf("invalid cid version")
}
}

// FormatOption is a format option.
type FormatOption func(f *Format)

// OptCodec configures the format to use the specified IPLD codec.
func OptCodec(codec uint64) FormatOption {
return func(f *Format) {
f.codec = codec
}
}

// OptInline configures the format to auto-inline (using the identity hash
// function) objects at most maxSize in length.
//
// Specify a value < 0 to disable auto-inlining.
func OptInline(maxSize int) FormatOption {
return func(f *Format) {
f.inlineMax = maxSize
}
}

// TODO: Split length and hash?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(discuss)


// OptHash sets the hash function to use in the format. Pass -1 as the length to
// use the default.
func OptHash(hash uint64, length int) FormatOption {
return func(f *Format) {
f.mhType = hash
f.mhLength = length
}
}

// TODO: Do we actually want this or should users always extend Format
// That is, DagCBORFormat.With(OptHash(...))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(discuss)


// NewFormat constructs a new CID format. It defaults to:
//
// * The DagCBOR format.
// * The SHA256 hash function.
func NewFormat(opts ...FormatOption) Format {
return DagCBORFormat.With(opts...)
}