github.com/ipld/go-ipld-prime@v0.21.0/linking/linkingExamples_test.go (about)

     1  package linking_test
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/ipfs/go-cid"
     7  
     8  	_ "github.com/ipld/go-ipld-prime/codec/dagcbor"
     9  	"github.com/ipld/go-ipld-prime/fluent"
    10  	"github.com/ipld/go-ipld-prime/linking"
    11  	cidlink "github.com/ipld/go-ipld-prime/linking/cid"
    12  	"github.com/ipld/go-ipld-prime/node/basicnode"
    13  	"github.com/ipld/go-ipld-prime/storage/memstore"
    14  )
    15  
    16  // storage is a map where we'll store serialized IPLD data.
    17  //
    18  // ExampleLinkSystem_Store will put data into this;
    19  // ExampleLinkSystem_Load will read out from it.
    20  //
    21  // In a real program, you'll probably make functions to load and store from disk,
    22  // or some network storage, or... whatever you want, really :)
    23  var store = memstore.Store{}
    24  
    25  // TODO: These examples are really heavy on CIDs and the multicodec and multihash magic tables.
    26  // It would be good to have examples that create and use less magical LinkSystem constructions, too.
    27  
    28  func ExampleLinkSystem_Store() {
    29  	// Creating a Link is done by choosing a concrete link implementation (typically, CID),
    30  	//  getting a LinkSystem that knows how to work with that, and then using the LinkSystem methods.
    31  
    32  	// Let's get a LinkSystem.  We're going to be working with CID links,
    33  	//  so let's get the default LinkSystem that's ready to work with those.
    34  	lsys := cidlink.DefaultLinkSystem()
    35  
    36  	// We want to store the serialized data somewhere.
    37  	//  We'll use an in-memory store for this.  (It's a package scoped variable.)
    38  	//  You can use any kind of storage system here;
    39  	//   or if you need even more control, you could also write a function that conforms to the linking.BlockWriteOpener interface.
    40  	lsys.SetWriteStorage(&store)
    41  
    42  	// To create any links, first we need a LinkPrototype.
    43  	// This gathers together any parameters that might be needed when making a link.
    44  	// (For CIDs, the version, the codec, and the multihash type are all parameters we'll need.)
    45  	// Often, you can probably make this a constant for your whole application.
    46  	lp := cidlink.LinkPrototype{Prefix: cid.Prefix{
    47  		Version:  1,    // Usually '1'.
    48  		Codec:    0x71, // 0x71 means "dag-cbor" -- See the multicodecs table: https://github.com/multiformats/multicodec/
    49  		MhType:   0x13, // 0x20 means "sha2-512" -- See the multicodecs table: https://github.com/multiformats/multicodec/
    50  		MhLength: 64,   // sha2-512 hash has a 64-byte sum.
    51  	}}
    52  
    53  	// And we need some data to link to!  Here's a quick piece of example data:
    54  	n := fluent.MustBuildMap(basicnode.Prototype.Map, 1, func(na fluent.MapAssembler) {
    55  		na.AssembleEntry("hello").AssignString("world")
    56  	})
    57  
    58  	// Before we use the LinkService, NOTE:
    59  	//  There's a side-effecting import at the top of the file.  It's for the dag-cbor codec.
    60  	//  The CID LinkSystem defaults use a global registry called the multicodec table;
    61  	//  and the multicodec table is populated in part by the dag-cbor package when it's first imported.
    62  	// You'll need that side-effecting import, too, to copy this example.
    63  	//  It can happen anywhere in your program; once, in any package, is enough.
    64  	//  If you don't have this import, the codec will not be registered in the multicodec registry,
    65  	//  and when you use the LinkSystem we got from the cidlink package, it will return an error of type ErrLinkingSetup.
    66  	// If you initialize a custom LinkSystem, you can control this more directly;
    67  	//  these registry systems are only here as defaults.
    68  
    69  	// Now: time to apply the LinkSystem, and do the actual store operation!
    70  	lnk, err := lsys.Store(
    71  		linking.LinkContext{}, // The zero value is fine.  Configure it it you want cancellability or other features.
    72  		lp,                    // The LinkPrototype says what codec and hashing to use.
    73  		n,                     // And here's our data.
    74  	)
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  
    79  	// That's it!  We got a link.
    80  	fmt.Printf("link: %s\n", lnk)
    81  	fmt.Printf("concrete type: `%T`\n", lnk)
    82  
    83  	// Remember: the serialized data was also stored to the 'store' variable as a side-effect.
    84  	//  (We set this up back when we customized the LinkSystem.)
    85  	//  We'll pick this data back up again in the example for loading.
    86  
    87  	// Output:
    88  	// link: bafyrgqhai26anf3i7pips7q22coa4sz2fr4gk4q4sqdtymvvjyginfzaqewveaeqdh524nsktaq43j65v22xxrybrtertmcfxufdam3da3hbk
    89  	// concrete type: `cidlink.Link`
    90  }
    91  
    92  func ExampleLinkSystem_Load() {
    93  	// Let's say we want to load this link (it's the same one we created in ExampleLinkSystem_Store).
    94  	cid, _ := cid.Decode("bafyrgqhai26anf3i7pips7q22coa4sz2fr4gk4q4sqdtymvvjyginfzaqewveaeqdh524nsktaq43j65v22xxrybrtertmcfxufdam3da3hbk")
    95  	lnk := cidlink.Link{Cid: cid}
    96  
    97  	// Let's get a LinkSystem.  We're going to be working with CID links,
    98  	//  so let's get the default LinkSystem that's ready to work with those.
    99  	// (This is the same as we did in ExampleLinkSystem_Store.)
   100  	lsys := cidlink.DefaultLinkSystem()
   101  
   102  	// We need somewhere to go looking for any of the data we might want to load!
   103  	//  We'll use an in-memory store for this.  (It's a package scoped variable.)
   104  	//   (This particular memory store was filled with the data we'll load earlier, during ExampleLinkSystem_Store.)
   105  	//  You can use any kind of storage system here;
   106  	//   or if you need even more control, you could also write a function that conforms to the linking.BlockReadOpener interface.
   107  	lsys.SetReadStorage(&store)
   108  
   109  	// We'll need to decide what in-memory implementation of datamodel.Node we want to use.
   110  	//  Here, we'll use the "basicnode" implementation.  This is a good getting-started choice.
   111  	//   But you could also use other implementations, or even a code-generated type with special features!
   112  	np := basicnode.Prototype.Any
   113  
   114  	// Before we use the LinkService, NOTE:
   115  	//  There's a side-effecting import at the top of the file.  It's for the dag-cbor codec.
   116  	//  See the comments in ExampleLinkSystem_Store for more discussion of this and why it's important.
   117  
   118  	// Apply the LinkSystem, and ask it to load our link!
   119  	n, err := lsys.Load(
   120  		linking.LinkContext{}, // The zero value is fine.  Configure it it you want cancellability or other features.
   121  		lnk,                   // The Link we want to load!
   122  		np,                    // The NodePrototype says what kind of Node we want as a result.
   123  	)
   124  	if err != nil {
   125  		panic(err)
   126  	}
   127  
   128  	// Tada!  We have the data as node that we can traverse and use as desired.
   129  	fmt.Printf("we loaded a %s with %d entries\n", n.Kind(), n.Length())
   130  
   131  	// Output:
   132  	// we loaded a map with 1 entries
   133  }