Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
140 lines (116 sloc)
3.49 KB
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
| var protobuf = require('protocol-buffers') | |
| var stable = require('stable') | |
| var defined = require('defined') | |
| var multihashing = require('multihashing') | |
| var base58 = require('bs58') | |
| var multiline = require('multiline') | |
| // TODO(noffle): make this into its own module | |
| var schema = multiline(function () {/* | |
| message PBLink { | |
| optional bytes Hash = 1; | |
| optional string Name = 2; | |
| optional uint64 Tsize = 3; | |
| } | |
| message PBNode { | |
| repeated PBLink Links = 2; | |
| optional bytes Data = 1; | |
| } | |
| */}) | |
| var mdagpb = protobuf(schema) | |
| module.exports = Node | |
| Node.fromProtobuf = fromProtobuf | |
| function Node (data, links) { | |
| if (!(this instanceof Node)) return new Node(data, links) | |
| if (typeof data === 'string') { | |
| data = new Buffer(data) | |
| } | |
| if (!Buffer.isBuffer(data)) { | |
| throw new Error('data must be a Buffer object') | |
| } | |
| links = defined(links, []) | |
| // convert links from Nodes to Links | |
| if (typeof links === 'object') { | |
| if (Array.isArray(links)) { | |
| this.links = links | |
| } else { | |
| this.links = Object.keys(links).map(function (name) { | |
| return new Link(name, links[name].size, links[name].hash) | |
| }) | |
| } | |
| } else { | |
| throw new Error('links must be an object of name:node mappings or a list of links') | |
| } | |
| defineImmutableProperty(this, 'data', data) | |
| defineImmutableProperty(this, 'encoded', mdagpb.PBNode.encode(toProtoBuf(this))) | |
| defineImmutableProperty(this, 'hash', multihashing(this.encoded, 'sha2-256')) | |
| defineImmutableProperty(this, 'size', computeSize(this)) | |
| defineImmutableProperty(this, 'multihash', base58.encode(this.hash)) | |
| this.asLink = function (name) { | |
| return new Link(name, this.size, this.hash) | |
| } | |
| // A node's size is the total size of the data addressed by node, plus the | |
| // sum of the sizes of the nodes it links to. | |
| function computeSize (node) { | |
| if (!node.encoded) { | |
| throw new Error('no value for \'encoded\' -- this should not happen') | |
| } | |
| var size = node.encoded.length | |
| for (var i = 0; i < node.links.length; i++) { | |
| size += node.links[i].size | |
| } | |
| return size | |
| } | |
| // Helper method to get a protobuf object equivalent | |
| function toProtoBuf (node) { | |
| var pbn = {} | |
| if (node.data && node.data.length > 0) { | |
| pbn.Data = node.data | |
| } else { | |
| pbn.Data = null | |
| } | |
| if (node.links.length > 0) { | |
| pbn.Links = [] | |
| for (var i = 0; i < node.links.length; i++) { | |
| var link = node.links[i] | |
| pbn.Links.push({ | |
| Hash: link.hash, | |
| Name: link.name, | |
| Tsize: link.size | |
| }) | |
| } | |
| } else { | |
| pbn.Links = null | |
| } | |
| return pbn | |
| } | |
| } | |
| function fromProtobuf (data) { | |
| // extract struct from protobuf | |
| var pbn = mdagpb.PBNode.decode(data) | |
| // extract and sort links | |
| var links = [] | |
| for (var i = 0; i < pbn.Links.length; i++) { | |
| var link = pbn.Links[i] | |
| var lnk = new Link(link.Name, link.Tsize, link.Hash) | |
| links.push(lnk) | |
| } | |
| stable.inplace(links, linkSort) | |
| var innerData = defined(pbn.Data, new Buffer(0)) | |
| return new Node(innerData, links) | |
| function linkSort (a, b) { | |
| return a.name.localeCompare(b.name) | |
| } | |
| } | |
| // Link represents a directional connection from one IPFS Merkle DAG Node to another. | |
| function Link (name, size, hash) { | |
| defineImmutableProperty(this, 'name', name) | |
| defineImmutableProperty(this, 'size', size) | |
| defineImmutableProperty(this, 'hash', hash) | |
| } | |
| function defineImmutableProperty (obj, name, value) { | |
| Object.defineProperty(obj, name, { | |
| writable: false, | |
| enumerable: true, | |
| value: value | |
| }) | |
| } |