public byte[] serialize() { Dictionary <string, byte[]> bldata = new Dictionary <string, byte[]>(); // -"-v1" // RelativeFilePath = Encoding.UTF8.GetBytes(string) // BytePosition = BitConverter.GetBytes(int) // ByteLength = BitConverter.GetBytes(int) // -"-v2" // BlobType = BitConverter.GetBytes(int) // -v3 // Required: breaks compatability // ReferenceCount = BitConverter.GetBytes(int) // -v4 // Required // IsMultiBlockReference = BitConverter.GetBytes(bool) // -v5 // Required // BSetReferenceCounts.BackupSets = // BSetReferenceCounts.ReferenceCounts = // -v6 // BlobType removed // IsMultiBlockReference removed // -v7 // IsMultiBlockReference readded // -v8 // BlockHashes = enum_encode // -v9 // EncryptedHash = bytes bldata.Add("EncryptedHash-v9", EncryptedHash == null ? new byte[0] : EncryptedHash); bldata.Add("RelativeFilePath-v1", Encoding.UTF8.GetBytes(RelativeFilePath)); bldata.Add("ByteLength-v1", BitConverter.GetBytes(ByteLength)); bldata.Add("BSetReferenceCounts.BackupSets-v5", BinaryEncoding.enum_encode(BSetReferenceCounts.Keys.Select(bsr => bsr.serialize()))); bldata.Add("BSetReferenceCounts.ReferenceCounts-v5", BinaryEncoding.enum_encode(BSetReferenceCounts.Values.Select(rc => BitConverter.GetBytes(rc)))); bldata.Add("IsMultiBlockReference-v7", BitConverter.GetBytes(BlockHashes != null)); if (BlockHashes != null) { bldata.Add("BlockHashes-v8", BinaryEncoding.enum_encode(BlockHashes)); } return(BinaryEncoding.dict_encode(bldata)); }
/// <summary> /// Store this node and its descendents in a blobstore /// Breaks with circular references, but these should only occur /// with hard- (and soft-?) -links TODO: handle links /// </summary> /// <param name="blobs"></param> /// <param name="storeGetHash">Function called to store node data, returns hash</param> /// <returns>The hash of the stored tree and a tree of its child hashes.</returns> public (byte[] nodehash, HashTreeNode node) Store(Func <byte[], byte[]> storeGetHash) { List <(byte[] nodehash, HashTreeNode?node)> children = new List <(byte[] nodehash, HashTreeNode?node)>(); List <byte[]> dirhashes = new List <byte[]>(); foreach (MetadataNode dir in Directories.Values) { var(newhash, newnode) = dir.Store(storeGetHash); dirhashes.Add(newhash); children.Add((newhash, newnode)); } foreach (var fm in Files.Values.AsEnumerable()) { if (fm.FileHash == null) { throw new NullReferenceException("Stored filehashes cannot be null"); } children.Add((fm.FileHash, null)); } Dictionary <string, byte[]> mtdata = new Dictionary <string, byte[]>(); // -"-v1" // DirMetadata = FileMetadata DirMetadata.serialize() // Directories = enum_encode([Directories.Values MetadataNode.serialize(),... ]) // Files = enum_encode([Files.Values FileMetadata.serialize(),... ]) // -"-v2" // Directories = enum_encode([dirrefs,...]) // "-v3" // DirectoriesMultiblock = enum_encode([BitConverter.GetBytes(multiblock),...]) // -v4 // removed DirectoriesMultiblock mtdata.Add("DirMetadata-v1", DirMetadata.serialize()); mtdata.Add("Files-v1", BinaryEncoding.enum_encode(Files.Values.AsEnumerable() .Select(fm => fm.serialize()))); mtdata.Add("Directories-v2", BinaryEncoding.enum_encode(dirhashes)); byte[] nodehash = storeGetHash(BinaryEncoding.dict_encode(mtdata)); HashTreeNode node = new HashTreeNode(children); return(nodehash, node); }