import { assert } from "@fluidframework/common-utils" ; import { ISequencedDocumentMessage , ISnapshotTree } from "@fluidframework/protocol-definitions" ; import { ISnapshotContents } from "./odspUtils" ; import { ReadBuffer } from "./ReadBufferUtils" ; import { assertBlobCoreInstance , assertBoolInstance , assertNodeCoreInstance , assertNumberInstance , getAndValidateNodeProps , NodeCore , TreeBuilder , } from "./zipItDataRepresentationUtils" ; export const snapshotMinReadVersion = "1.0" ; interface ISnapshotSection { snapshotTree : ISnapshotTree ; sequenceNumber : number ; } param node function readBlobSection ( node ) { const blobs = new Map ( ) ; for ( let count = 0 ; count < node . length ; ++ count ) { const blob = node . getNode ( count ) ; const records = getAndValidateNodeProps ( blob , [ "id" , "data" ] ) ; assertBlobCoreInstance ( records . data , "data should be of BlobCore type" ) ; assertBlobCoreInstance ( records . id , "blob id should be of BlobCore type" ) ; blobs . set ( records . id . toString ( ) , records . data . arrayBuffer ) ; } return blobs ; } param node function readOpsSection ( node ) { const ops = [ ] ; const records = getAndValidateNodeProps ( node , [ "firstSequenceNumber" , "deltas" ] ) ; assertNumberInstance ( records . firstSequenceNumber , "Seq number should be a number" ) ; assertNodeCoreInstance ( records . deltas , "Deltas should be a Node" ) ; for ( let i = 0 ; i < records . deltas . length ; ++ i ) { ops . push ( JSON . parse ( records . deltas . getString ( i ) ) ) ; } assert ( records . firstSequenceNumber . valueOf ( ) === ops [ 0 ] . sequenceNumber , 0x280 ) ; return ops ; } param node function readTreeSection ( node ) { const snapshotTree = { blobs : { } , commits : { } , trees : { } } ; for ( let count = 0 ; count < node . length ; count ++ ) { const treeNode = node . getNode ( count ) ; const records = getAndValidateNodeProps ( treeNode , [ "name" , "value" , "children" , "unreferenced" ] , false ) ; assertBlobCoreInstance ( records . name , "Path should be of BlobCore" ) ; const path = records . name . toString ( ) ; if ( records . value !== undefined ) { assertBlobCoreInstance ( records . value , "Blob value should be BlobCore" ) ; snapshotTree . blobs [ path ] = records . value . toString ( ) ; } else { assertNodeCoreInstance ( records . children , "Trees should be of type NodeCore" ) ; snapshotTree . trees [ path ] = readTreeSection ( records . children ) ; } if ( records . unreferenced !== undefined ) { assertBoolInstance ( records . unreferenced , "Unreferenced flag should be bool" ) ; const unreferenced = records . unreferenced . valueOf ( ) ; assert ( unreferenced , 0x281 ) ; snapshotTree . unreferenced = unreferenced ; } } return snapshotTree ; } param node function readSnapshotSection ( node ) { const records = getAndValidateNodeProps ( node , [ "id" , "sequenceNumber" , "treeNodes" ] ) ; assertNodeCoreInstance ( records . treeNodes , "TreeNodes should be of type NodeCore" ) ; assertNumberInstance ( records . sequenceNumber , "sequenceNumber should be of type number" ) ; assertBlobCoreInstance ( records . id , "snapshotId should be BlobCore" ) ; const snapshotTree = readTreeSection ( records . treeNodes ) ; snapshotTree . id = records . id . toString ( ) ; const sequenceNumber = records . sequenceNumber . valueOf ( ) ; return { sequenceNumber , snapshotTree } ; } param buffer returns export function parseCompactSnapshotResponse ( buffer ) { const builder = TreeBuilder . load ( buffer ) ; assert ( builder . length === 1 , 0x219 ) ; const root = builder . getNode ( 0 ) ; const records = getAndValidateNodeProps ( root , [ "mrv" , "cv" , "snapshot" , "blobs" , "deltas" ] ) ; assertBlobCoreInstance ( records . mrv , "minReadVersion should be of BlobCore type" ) ; assertBlobCoreInstance ( records . cv , "createVersion should be of BlobCore type" ) ; assert ( snapshotMinReadVersion >= records . mrv . toString ( ) , 0x20f ) ; assert ( records . cv . toString ( ) >= snapshotMinReadVersion , 0x210 ) ; assertNodeCoreInstance ( records . snapshot , "Snapshot should be of type NodeCore" ) ; assertNodeCoreInstance ( records . blobs , "TreeBlobs should be of type NodeCore" ) ; assertNodeCoreInstance ( records . deltas , "Deltas should be of type NodeCore" ) ; return { ... readSnapshotSection ( records . snapshot ) , blobs : readBlobSection ( records . blobs ) , ops : readOpsSection ( records . deltas ) } ; }