Last active
June 22, 2022 13:36
-
-
Save kaloyan-raev/d4def01c818129a490eb8d4fe8b6fb68 to your computer and use it in GitHub Desktop.
Minimal code for calculating IPFS CID
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"io" | |
"os" | |
"sync" | |
cid "github.com/ipfs/go-cid" | |
chunker "github.com/ipfs/go-ipfs-chunker" | |
dagtest "github.com/ipfs/go-merkledag/test" | |
balanced "github.com/ipfs/go-unixfs/importer/balanced" | |
ihelper "github.com/ipfs/go-unixfs/importer/helpers" | |
"golang.org/x/sync/errgroup" | |
) | |
func main() { | |
file, err := os.Open("/home/kaloyan/Videos/ben.mkv") | |
if err != nil { | |
panic(err) | |
} | |
defer file.Close() | |
reader := NewIpfsCidReader(file) | |
_, err = io.Copy(io.Discard, reader) | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println(reader.Cid()) | |
} | |
func IpfsCid(r io.Reader) (cid.Cid, error) { | |
params := ihelper.DagBuilderParams{ | |
Dagserv: dagtest.Mock(), | |
Maxlinks: ihelper.DefaultLinksPerBlock, | |
} | |
db, err := params.New(chunker.DefaultSplitter(r)) | |
if err != nil { | |
return cid.Cid{}, err | |
} | |
node, err := balanced.Layout(db) | |
if err != nil { | |
return cid.Cid{}, err | |
} | |
return node.Cid(), err | |
} | |
type IpfsCidReader struct { | |
reader io.Reader | |
pipeReader *io.PipeReader | |
pipeWriter *io.PipeWriter | |
once sync.Once | |
group errgroup.Group | |
cid cid.Cid | |
} | |
func NewIpfsCidReader(r io.Reader) *IpfsCidReader { | |
pipeReader, pipeWriter := io.Pipe() | |
return &IpfsCidReader{ | |
reader: io.TeeReader(r, pipeWriter), | |
pipeReader: pipeReader, | |
pipeWriter: pipeWriter, | |
} | |
} | |
func (r *IpfsCidReader) Read(p []byte) (n int, err error) { | |
r.once.Do(func() { | |
r.group.Go(func() error { | |
cid, err := IpfsCid(r.pipeReader) | |
r.cid = cid | |
return err | |
}) | |
}) | |
n, err = r.reader.Read(p) | |
if err != nil { | |
r.pipeWriter.CloseWithError(err) | |
} | |
return n, err | |
} | |
func (r *IpfsCidReader) Cid() (cid.Cid, error) { | |
err := r.group.Wait() | |
return r.cid, err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment