import { FluidObject , IFluidHandle , IFluidLoadable , IFluidObject } from "@fluidframework/core-interfaces" ; import { BaseSegment , createGroupOp , IJSONSegment , ISegment , LocalReferenceCollection , PropertySet , } from "@fluidframework/merge-tree" ; import { IChannelAttributes , IFluidDataStoreRuntime , IChannelServices , IChannelFactory , Serializable , Jsonable , } from "@fluidframework/datastore-definitions" ; import { ISharedObject } from "@fluidframework/shared-object-base" ; import { pkgVersion } from "./packageVersion" ; import { SharedSegmentSequence , SubSequence } from "./" ; deprecated export class PaddingSegment extends BaseSegment { public static readonly typeString = "PaddingSegment" ; public static is ( segment ) { return segment . type === PaddingSegment . typeString ; } public static fromJSONObject ( spec ) { if ( spec && typeof spec === "object" && "pad" in spec ) { const segment = new PaddingSegment ( spec . pad ) ; if ( spec . props ) { segment . addProperties ( spec . props ) ; } return segment ; } return undefined ; } public readonly type = PaddingSegment . typeString ; constructor ( size ) { super ( ) ; this . cachedLength = size ; } public toJSONObject ( ) { return { pad : this . cachedLength , props : this . properties } ; } public clone ( start = 0 , end ? ) { const b = new PaddingSegment ( this . cachedLength ) ; this . cloneInto ( b ) ; return b ; } public canAppend ( segment ) { return PaddingSegment . is ( segment ) ; } public toString ( ) { return `[padding: ${ this . cachedLength }]` ; } public append ( segment ) { if ( ! PaddingSegment . is ( segment ) ) { throw new Error ( "can only append padding segment" ) ; } LocalReferenceCollection . append ( this , segment ) ; this . cachedLength += segment . cachedLength ; } public removeRange ( start , end ) { this . cachedLength -= ( end - start ) ; return ( this . cachedLength === 0 ) ; } protected createSplitSegmentAt ( pos ) { const leftLength = pos ; const rightLength = this . cachedLength - pos ; this . cachedLength = leftLength ; return new PaddingSegment ( rightLength ) ; } } deprecated export type SparseMatrixItem = Serializable ; deprecated export class RunSegment extends SubSequence < SparseMatrixItem > { public static readonly typeString = "RunSegment" ; public static is ( segment ) { return segment . type === RunSegment . typeString ; } public static fromJSONObject ( spec ) { if ( spec && typeof spec === "object" && "items" in spec ) { const segment = new RunSegment ( spec . items ) ; if ( spec . props ) { segment . addProperties ( spec . props ) ; } return segment ; } return undefined ; } public readonly type = RunSegment . typeString ; private tags : any [ ] ; constructor ( public items ) { super ( items ) ; this . tags = new Array ( items . length ) . fill ( undefined ) ; } public clone ( start = 0 , end ? ) { const b = new RunSegment ( this . items . slice ( start , end ) ) ; if ( this . tags ) { b . tags = this . tags . slice ( start , end ) ; } this . cloneInto ( b ) ; return b ; } public append ( segment ) { super . append ( segment ) ; const asRun = segment as RunSegment ; if ( asRun . tags ) { if ( this . tags ) { this . tags . splice ( this . items . length , 0 , ... asRun . tags ) ; } } return this ; } public removeRange ( start , end ) { this . tags . splice ( start , end - start ) ; return super . removeRange ( start , end ) ; } public getTag ( pos ) { return this . tags [ pos ] ; } public setTag ( pos , tag ) { this . tags [ pos ] = tag ; } protected createSplitSegmentAt ( pos ) { if ( pos > 0 ) { const remainingItems = this . items . slice ( pos ) ; this . items = this . items . slice ( 0 , pos ) ; this . cachedLength = this . items . length ; const leafSegment = new RunSegment ( remainingItems ) ; leafSegment . tags = this . tags . slice ( pos ) ; this . tags . length = pos ; return leafSegment ; } } } deprecated export type MatrixSegment = RunSegment | PaddingSegment ; deprecated export const maxCol = 0x200000 ; deprecated export const maxCols = maxCol + 1 ; deprecated export const maxRow = 0xFFFFFFFF ; deprecated export const maxRows = maxRow + 1 ; deprecated export const maxCellPosition = maxCol * maxRow ; deprecated export const rowColToPosition = ( row , col ) => row * maxCols + col ; deprecated export function positionToRowCol ( position ) { const row = Math . floor ( position / maxCols ) ; const col = position - ( row * maxCols ) ; return { row , col } ; } deprecated export class SparseMatrix extends SharedSegmentSequence < MatrixSegment > { param runtime param id returns public static create ( runtime , id ? ) { return runtime . createChannel ( id , SparseMatrixFactory . Type ) as SparseMatrix ; } returns public static getFactory ( ) { return new SparseMatrixFactory ( ) ; } constructor ( document , public id , attributes ) { super ( document , id , attributes , SparseMatrixFactory . segmentFromSpec ) ; } public get numRows ( ) { return positionToRowCol ( this . getLength ( ) ) . row ; } public setItems ( row , col , values , props ? ) { const start = rowColToPosition ( row , col ) ; const end = start + values . length ; const segment = new RunSegment ( values ) ; if ( props ) { segment . addProperties ( props ) ; } this . replaceRange ( start , end , segment ) ; } public getItem ( row , col ) { const pos = rowColToPosition ( row , col ) ; const { segment , offset } = this . getContainingSegment ( pos ) ; if ( RunSegment . is ( segment ) ) { return segment . items [ offset ] ; } else if ( PaddingSegment . is ( segment ) ) { return undefined ; } throw new Error ( `Unrecognized Segment type` ) ; } public getTag ( row , col ) { const { segment , offset } = this . getSegment ( row , col ) ; if ( RunSegment . is ( segment ) ) { return segment . getTag ( offset ) ; } return undefined ; } public setTag ( row , col , tag ) { const { segment , offset } = this . getSegment ( row , col ) ; if ( RunSegment . is ( segment ) ) { segment . setTag ( offset , tag ) ; } else if ( tag !== undefined ) { throw new Error ( `Must not attempt to set tags on '${ segment . constructor . name }'.` ) ; } } public insertRows ( row , numRows ) { const pos = rowColToPosition ( row , 0 ) ; const size = maxCols * numRows ; const segment = new PaddingSegment ( size ) ; const insertOp = this . client . insertSegmentLocal ( pos , segment ) ; if ( insertOp ) { this . submitSequenceMessage ( insertOp ) ; } } public removeRows ( row , numRows ) { const pos = rowColToPosition ( row , 0 ) ; const size = maxCols * numRows ; this . removeRange ( pos , pos + size ) ; } public insertCols ( col , numCols ) { this . moveAsPadding ( maxCol - numCols , col , numCols ) ; } public removeCols ( col , numCols ) { this . moveAsPadding ( col , maxCol - numCols , numCols ) ; } public annotatePosition ( row , col , props ) { const pos = rowColToPosition ( row , col ) ; this . annotateRange ( pos , pos + 1 , props ) ; } public getPositionProperties ( row , col ) { const pos = rowColToPosition ( row , col ) ; return this . getPropertiesAtPosition ( pos ) ; } private moveAsPadding ( srcCol , destCol , numCols ) { const removeColStart = srcCol ; const removeColEnd = srcCol + numCols ; const ops = [ ] ; for ( let r = 0 , rowStart = 0 ; r < this . numRows ; r ++ , rowStart += maxCols ) { ops . push ( this . client . removeRangeLocal ( rowStart + removeColStart , rowStart + removeColEnd ) ) ; const insertPos = rowStart + destCol ; const segment = new PaddingSegment ( numCols ) ; ops . push ( this . client . insertSegmentLocal ( insertPos , segment ) ) ; } this . submitSequenceMessage ( createGroupOp ( ... ops ) ) ; } private getSegment ( row , col ) { const pos = rowColToPosition ( row , col ) ; return this . getContainingSegment ( pos ) ; } } deprecated export class SparseMatrixFactory implements IChannelFactory { public static Type = "https://graph.microsoft.com/types/mergeTree/sparse-matrix" ; public static Attributes : IChannelAttributes = { type : SparseMatrixFactory . Type , snapshotFormatVersion : "0.1" , packageVersion : pkgVersion } ; public static segmentFromSpec ( spec ) { const maybePadding = PaddingSegment . fromJSONObject ( spec ) ; if ( maybePadding ) { return maybePadding ; } const maybeRun = RunSegment . fromJSONObject ( spec ) ; if ( maybeRun ) { return maybeRun ; } throw new Error ( `Unrecognized IJSONObject: '${ JSON . stringify ( spec ) }'` ) ; } public get type ( ) { return SparseMatrixFactory . Type ; } public get attributes ( ) { return SparseMatrixFactory . Attributes ; } /**
     * {@inheritDoc @fluidframework/datastore-definitions#IChannelFactory.load}
     */ public async load ( runtime , id , services , attributes ) { const sharedObject = new SparseMatrix ( runtime , id , attributes ) ; await sharedObject . load ( services ) ; return sharedObject ; } public create ( document , id ) { const sharedObject = new SparseMatrix ( document , id , this . attributes ) ; sharedObject . initializeLocal ( ) ; return sharedObject ; } }