github.com/onflow/atree@v0.6.0/array_debug.go (about)

     1  /*
     2   * Atree - Scalable Arrays and Ordered Maps
     3   *
     4   * Copyright 2021 Dapper Labs, Inc.
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *   http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package atree
    20  
    21  import (
    22  	"bytes"
    23  	"errors"
    24  	"fmt"
    25  	"reflect"
    26  	"strings"
    27  
    28  	"github.com/fxamacker/cbor/v2"
    29  )
    30  
    31  type ArrayStats struct {
    32  	Levels            uint64
    33  	ElementCount      uint64
    34  	MetaDataSlabCount uint64
    35  	DataSlabCount     uint64
    36  	StorableSlabCount uint64
    37  }
    38  
    39  func (s *ArrayStats) SlabCount() uint64 {
    40  	return s.DataSlabCount + s.MetaDataSlabCount + s.StorableSlabCount
    41  }
    42  
    43  // GetArrayStats returns stats about array slabs.
    44  func GetArrayStats(a *Array) (ArrayStats, error) {
    45  	level := uint64(0)
    46  	metaDataSlabCount := uint64(0)
    47  	dataSlabCount := uint64(0)
    48  	storableSlabCount := uint64(0)
    49  
    50  	nextLevelIDs := []StorageID{a.StorageID()}
    51  
    52  	for len(nextLevelIDs) > 0 {
    53  
    54  		ids := nextLevelIDs
    55  
    56  		nextLevelIDs = []StorageID(nil)
    57  
    58  		for _, id := range ids {
    59  
    60  			slab, err := getArraySlab(a.Storage, id)
    61  			if err != nil {
    62  				// Don't need to wrap error as external error because err is already categorized by getArraySlab().
    63  				return ArrayStats{}, err
    64  			}
    65  
    66  			if slab.IsData() {
    67  				dataSlabCount++
    68  
    69  				childStorables := slab.ChildStorables()
    70  				for _, s := range childStorables {
    71  					if _, ok := s.(StorageIDStorable); ok {
    72  						storableSlabCount++
    73  					}
    74  				}
    75  			} else {
    76  				metaDataSlabCount++
    77  
    78  				for _, storable := range slab.ChildStorables() {
    79  					id, ok := storable.(StorageIDStorable)
    80  					if !ok {
    81  						return ArrayStats{}, NewFatalError(fmt.Errorf("metadata slab's child storables are not of type StorageIDStorable"))
    82  					}
    83  					nextLevelIDs = append(nextLevelIDs, StorageID(id))
    84  				}
    85  			}
    86  		}
    87  
    88  		level++
    89  
    90  	}
    91  
    92  	return ArrayStats{
    93  		Levels:            level,
    94  		ElementCount:      a.Count(),
    95  		MetaDataSlabCount: metaDataSlabCount,
    96  		DataSlabCount:     dataSlabCount,
    97  		StorableSlabCount: storableSlabCount,
    98  	}, nil
    99  }
   100  
   101  // PrintArray prints array slab data to stdout.
   102  func PrintArray(a *Array) {
   103  	dumps, err := DumpArraySlabs(a)
   104  	if err != nil {
   105  		fmt.Println(err)
   106  		return
   107  	}
   108  	fmt.Println(strings.Join(dumps, "\n"))
   109  }
   110  
   111  func DumpArraySlabs(a *Array) ([]string, error) {
   112  	var dumps []string
   113  
   114  	nextLevelIDs := []StorageID{a.StorageID()}
   115  
   116  	var overflowIDs []StorageID
   117  
   118  	level := 0
   119  	for len(nextLevelIDs) > 0 {
   120  
   121  		ids := nextLevelIDs
   122  
   123  		nextLevelIDs = []StorageID(nil)
   124  
   125  		for _, id := range ids {
   126  
   127  			slab, err := getArraySlab(a.Storage, id)
   128  			if err != nil {
   129  				// Don't need to wrap error as external error because err is already categorized by getArraySlab().
   130  				return nil, err
   131  			}
   132  
   133  			if slab.IsData() {
   134  				dataSlab := slab.(*ArrayDataSlab)
   135  				dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, dataSlab))
   136  
   137  				childStorables := dataSlab.ChildStorables()
   138  				for _, e := range childStorables {
   139  					if id, ok := e.(StorageIDStorable); ok {
   140  						overflowIDs = append(overflowIDs, StorageID(id))
   141  					}
   142  				}
   143  
   144  			} else {
   145  				meta := slab.(*ArrayMetaDataSlab)
   146  				dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, meta))
   147  
   148  				for _, storable := range slab.ChildStorables() {
   149  					id, ok := storable.(StorageIDStorable)
   150  					if !ok {
   151  						return nil, NewFatalError(errors.New("metadata slab's child storables are not of type StorageIDStorable"))
   152  					}
   153  					nextLevelIDs = append(nextLevelIDs, StorageID(id))
   154  				}
   155  			}
   156  		}
   157  
   158  		level++
   159  	}
   160  
   161  	for _, id := range overflowIDs {
   162  		slab, found, err := a.Storage.Retrieve(id)
   163  		if err != nil {
   164  			// Wrap err as external error (if needed) because err is returned by SlabStorage interface.
   165  			return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to retrieve slab %s", id))
   166  		}
   167  		if !found {
   168  			return nil, NewSlabNotFoundErrorf(id, "slab not found during array slab dump")
   169  		}
   170  		dumps = append(dumps, fmt.Sprintf("overflow: %s", slab))
   171  	}
   172  
   173  	return dumps, nil
   174  }
   175  
   176  type TypeInfoComparator func(TypeInfo, TypeInfo) bool
   177  
   178  func ValidArray(a *Array, typeInfo TypeInfo, tic TypeInfoComparator, hip HashInputProvider) error {
   179  
   180  	extraData := a.root.ExtraData()
   181  	if extraData == nil {
   182  		return NewFatalError(fmt.Errorf("root slab %d doesn't have extra data", a.root.ID()))
   183  	}
   184  
   185  	// Verify that extra data has correct type information
   186  	if typeInfo != nil && !tic(extraData.TypeInfo, typeInfo) {
   187  		return NewFatalError(fmt.Errorf(
   188  			"root slab %d type information %v is wrong, want %v",
   189  			a.root.ID(),
   190  			extraData.TypeInfo,
   191  			typeInfo,
   192  		))
   193  	}
   194  
   195  	computedCount, dataSlabIDs, nextDataSlabIDs, err :=
   196  		validArraySlab(tic, hip, a.Storage, a.root.Header().id, 0, nil, []StorageID{}, []StorageID{})
   197  	if err != nil {
   198  		// Don't need to wrap error as external error because err is already categorized by validArraySlab().
   199  		return err
   200  	}
   201  
   202  	// Verify array count
   203  	if computedCount != uint32(a.Count()) {
   204  		return NewFatalError(fmt.Errorf("root slab %d count %d is wrong, want %d", a.root.ID(), a.Count(), computedCount))
   205  	}
   206  
   207  	// Verify next data slab ids
   208  	if !reflect.DeepEqual(dataSlabIDs[1:], nextDataSlabIDs) {
   209  		return NewFatalError(fmt.Errorf("chained next data slab ids %v are wrong, want %v",
   210  			nextDataSlabIDs, dataSlabIDs[1:]))
   211  	}
   212  
   213  	return nil
   214  }
   215  
   216  func validArraySlab(
   217  	tic TypeInfoComparator,
   218  	hip HashInputProvider,
   219  	storage SlabStorage,
   220  	id StorageID,
   221  	level int,
   222  	headerFromParentSlab *ArraySlabHeader,
   223  	dataSlabIDs []StorageID,
   224  	nextDataSlabIDs []StorageID,
   225  ) (
   226  	elementCount uint32,
   227  	_dataSlabIDs []StorageID,
   228  	_nextDataSlabIDs []StorageID,
   229  	err error,
   230  ) {
   231  
   232  	slab, err := getArraySlab(storage, id)
   233  	if err != nil {
   234  		// Don't need to wrap error as external error because err is already categorized by getArraySlab().
   235  		return 0, nil, nil, err
   236  	}
   237  
   238  	if level > 0 {
   239  		// Verify that non-root slab doesn't have extra data
   240  		if slab.ExtraData() != nil {
   241  			return 0, nil, nil, NewFatalError(fmt.Errorf("non-root slab %d has extra data", id))
   242  		}
   243  
   244  		// Verify that non-root slab doesn't underflow
   245  		if underflowSize, underflow := slab.IsUnderflow(); underflow {
   246  			return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d underflows by %d bytes", id, underflowSize))
   247  		}
   248  
   249  	}
   250  
   251  	// Verify that slab doesn't overflow
   252  	if slab.IsFull() {
   253  		return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d overflows", id))
   254  	}
   255  
   256  	// Verify that header is in sync with header from parent slab
   257  	if headerFromParentSlab != nil {
   258  		if !reflect.DeepEqual(*headerFromParentSlab, slab.Header()) {
   259  			return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d header %+v is different from header %+v from parent slab",
   260  				id, slab.Header(), headerFromParentSlab))
   261  		}
   262  	}
   263  
   264  	if slab.IsData() {
   265  		dataSlab, ok := slab.(*ArrayDataSlab)
   266  		if !ok {
   267  			return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d is not ArrayDataSlab", id))
   268  		}
   269  
   270  		// Verify that element count is the same as header.count
   271  		if uint32(len(dataSlab.elements)) != dataSlab.header.count {
   272  			return 0, nil, nil, NewFatalError(fmt.Errorf("data slab %d header count %d is wrong, want %d",
   273  				id, dataSlab.header.count, len(dataSlab.elements)))
   274  		}
   275  
   276  		// Verify that aggregated element size + slab prefix is the same as header.size
   277  		computedSize := uint32(arrayDataSlabPrefixSize)
   278  		if level == 0 {
   279  			computedSize = uint32(arrayRootDataSlabPrefixSize)
   280  		}
   281  		for _, e := range dataSlab.elements {
   282  
   283  			// Verify element size is <= inline size
   284  			if e.ByteSize() > uint32(MaxInlineArrayElementSize) {
   285  				return 0, nil, nil, NewFatalError(fmt.Errorf("data slab %d element %s size %d is too large, want < %d",
   286  					id, e, e.ByteSize(), MaxInlineArrayElementSize))
   287  			}
   288  
   289  			computedSize += e.ByteSize()
   290  		}
   291  
   292  		if computedSize != dataSlab.header.size {
   293  			return 0, nil, nil, NewFatalError(fmt.Errorf("data slab %d header size %d is wrong, want %d",
   294  				id, dataSlab.header.size, computedSize))
   295  		}
   296  
   297  		dataSlabIDs = append(dataSlabIDs, id)
   298  
   299  		if dataSlab.next != StorageIDUndefined {
   300  			nextDataSlabIDs = append(nextDataSlabIDs, dataSlab.next)
   301  		}
   302  
   303  		// Verify element
   304  		for _, e := range dataSlab.elements {
   305  			v, err := e.StoredValue(storage)
   306  			if err != nil {
   307  				// Wrap err as external error (if needed) because err is returned by Storable interface.
   308  				return 0, nil, nil, wrapErrorfAsExternalErrorIfNeeded(err,
   309  					fmt.Sprintf(
   310  						"data slab %s element %s can't be converted to value",
   311  						id, e,
   312  					))
   313  			}
   314  			err = ValidValue(v, nil, tic, hip)
   315  			if err != nil {
   316  				// Don't need to wrap error as external error because err is already categorized by ValidValue().
   317  				return 0, nil, nil, fmt.Errorf(
   318  					"data slab %d element %s isn't valid: %w",
   319  					id, e, err,
   320  				)
   321  			}
   322  		}
   323  
   324  		return dataSlab.header.count, dataSlabIDs, nextDataSlabIDs, nil
   325  	}
   326  
   327  	meta, ok := slab.(*ArrayMetaDataSlab)
   328  	if !ok {
   329  		return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d is not ArrayMetaDataSlab", id))
   330  	}
   331  
   332  	if level == 0 {
   333  		// Verify that root slab has more than one child slabs
   334  		if len(meta.childrenHeaders) < 2 {
   335  			return 0, nil, nil, NewFatalError(fmt.Errorf("root metadata slab %d has %d children, want at least 2 children ",
   336  				id, len(meta.childrenHeaders)))
   337  		}
   338  	}
   339  
   340  	// Verify childrenCountSum
   341  	if len(meta.childrenCountSum) != len(meta.childrenHeaders) {
   342  		return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d has %d childrenCountSum, want %d",
   343  			id, len(meta.childrenCountSum), len(meta.childrenHeaders)))
   344  	}
   345  
   346  	computedCount := uint32(0)
   347  	for i, h := range meta.childrenHeaders {
   348  		// Verify child slabs
   349  		var count uint32
   350  		count, dataSlabIDs, nextDataSlabIDs, err =
   351  			validArraySlab(tic, hip, storage, h.id, level+1, &h, dataSlabIDs, nextDataSlabIDs)
   352  		if err != nil {
   353  			// Don't need to wrap error as external error because err is already categorized by validArraySlab().
   354  			return 0, nil, nil, err
   355  		}
   356  
   357  		computedCount += count
   358  
   359  		// Verify childrenCountSum
   360  		if meta.childrenCountSum[i] != computedCount {
   361  			return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d childrenCountSum[%d] is %d, want %d",
   362  				id, i, meta.childrenCountSum[i], computedCount))
   363  		}
   364  	}
   365  
   366  	// Verify that aggregated element count is the same as header.count
   367  	if computedCount != meta.header.count {
   368  		return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d header count %d is wrong, want %d",
   369  			id, meta.header.count, computedCount))
   370  	}
   371  
   372  	// Verify that aggregated header size + slab prefix is the same as header.size
   373  	computedSize := uint32(len(meta.childrenHeaders)*arraySlabHeaderSize) + arrayMetaDataSlabPrefixSize
   374  	if computedSize != meta.header.size {
   375  		return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d header size %d is wrong, want %d",
   376  			id, meta.header.size, computedSize))
   377  	}
   378  
   379  	return meta.header.count, dataSlabIDs, nextDataSlabIDs, nil
   380  }
   381  
   382  // ValidArraySerialization traverses array tree and verifies serialization
   383  // by encoding, decoding, and re-encoding slabs.
   384  // It compares in-memory objects of original slab with decoded slab.
   385  // It also compares encoded data of original slab with encoded data of decoded slab.
   386  func ValidArraySerialization(
   387  	a *Array,
   388  	cborDecMode cbor.DecMode,
   389  	cborEncMode cbor.EncMode,
   390  	decodeStorable StorableDecoder,
   391  	decodeTypeInfo TypeInfoDecoder,
   392  	compare StorableComparator,
   393  ) error {
   394  	return validArraySlabSerialization(
   395  		a.Storage,
   396  		a.root.ID(),
   397  		cborDecMode,
   398  		cborEncMode,
   399  		decodeStorable,
   400  		decodeTypeInfo,
   401  		compare,
   402  	)
   403  }
   404  
   405  func validArraySlabSerialization(
   406  	storage SlabStorage,
   407  	id StorageID,
   408  	cborDecMode cbor.DecMode,
   409  	cborEncMode cbor.EncMode,
   410  	decodeStorable StorableDecoder,
   411  	decodeTypeInfo TypeInfoDecoder,
   412  	compare StorableComparator,
   413  ) error {
   414  
   415  	slab, err := getArraySlab(storage, id)
   416  	if err != nil {
   417  		// Don't need to wrap error as external error because err is already categorized by getArraySlab().
   418  		return err
   419  	}
   420  
   421  	// Encode slab
   422  	data, err := Encode(slab, cborEncMode)
   423  	if err != nil {
   424  		// Don't need to wrap error as external error because err is already categorized by Encode().
   425  		return err
   426  	}
   427  
   428  	// Decode encoded slab
   429  	decodedSlab, err := DecodeSlab(id, data, cborDecMode, decodeStorable, decodeTypeInfo)
   430  	if err != nil {
   431  		// Don't need to wrap error as external error because err is already categorized by DecodeSlab().
   432  		return err
   433  	}
   434  
   435  	// Re-encode decoded slab
   436  	dataFromDecodedSlab, err := Encode(decodedSlab, cborEncMode)
   437  	if err != nil {
   438  		// Don't need to wrap error as external error because err is already categorized by Encode().
   439  		return err
   440  	}
   441  
   442  	// Extra check: encoded data size == header.size
   443  	encodedExtraDataSize, err := getEncodedArrayExtraDataSize(slab.ExtraData(), cborEncMode)
   444  	if err != nil {
   445  		// Don't need to wrap error as external error because err is already categorized by getEncodedArrayExtraDataSize().
   446  		return err
   447  	}
   448  
   449  	// Need to exclude extra data size from encoded data size.
   450  	encodedSlabSize := uint32(len(data) - encodedExtraDataSize)
   451  	if slab.Header().size != encodedSlabSize {
   452  		return NewFatalError(fmt.Errorf("slab %d encoded size %d != header.size %d (encoded extra data size %d)",
   453  			id, encodedSlabSize, slab.Header().size, encodedExtraDataSize))
   454  	}
   455  
   456  	// Compare encoded data of original slab with encoded data of decoded slab
   457  	if !bytes.Equal(data, dataFromDecodedSlab) {
   458  		return NewFatalError(fmt.Errorf("slab %d encoded data is different from decoded slab's encoded data, got %v, want %v",
   459  			id, dataFromDecodedSlab, data))
   460  	}
   461  
   462  	if slab.IsData() {
   463  		dataSlab, ok := slab.(*ArrayDataSlab)
   464  		if !ok {
   465  			return NewFatalError(fmt.Errorf("slab %d is not ArrayDataSlab", id))
   466  		}
   467  
   468  		decodedDataSlab, ok := decodedSlab.(*ArrayDataSlab)
   469  		if !ok {
   470  			return NewFatalError(fmt.Errorf("decoded slab %d is not ArrayDataSlab", id))
   471  		}
   472  
   473  		// Compare slabs
   474  		err = arrayDataSlabEqual(
   475  			dataSlab,
   476  			decodedDataSlab,
   477  			storage,
   478  			cborDecMode,
   479  			cborEncMode,
   480  			decodeStorable,
   481  			decodeTypeInfo,
   482  			compare,
   483  		)
   484  		if err != nil {
   485  			// Don't need to wrap error as external error because err is already categorized by arrayDataSlabEqual().
   486  			return fmt.Errorf("data slab %d round-trip serialization failed: %w", id, err)
   487  		}
   488  
   489  		return nil
   490  	}
   491  
   492  	metaSlab, ok := slab.(*ArrayMetaDataSlab)
   493  	if !ok {
   494  		return NewFatalError(fmt.Errorf("slab %d is not ArrayMetaDataSlab", id))
   495  	}
   496  
   497  	decodedMetaSlab, ok := decodedSlab.(*ArrayMetaDataSlab)
   498  	if !ok {
   499  		return NewFatalError(fmt.Errorf("decoded slab %d is not ArrayMetaDataSlab", id))
   500  	}
   501  
   502  	// Compare slabs
   503  	err = arrayMetaDataSlabEqual(metaSlab, decodedMetaSlab)
   504  	if err != nil {
   505  		// Don't need to wrap error as external error because err is already categorized by arrayMetaDataSlabEqual().
   506  		return fmt.Errorf("metadata slab %d round-trip serialization failed: %w", id, err)
   507  	}
   508  
   509  	for _, h := range metaSlab.childrenHeaders {
   510  		// Verify child slabs
   511  		err = validArraySlabSerialization(
   512  			storage,
   513  			h.id,
   514  			cborDecMode,
   515  			cborEncMode,
   516  			decodeStorable,
   517  			decodeTypeInfo,
   518  			compare,
   519  		)
   520  		if err != nil {
   521  			// Don't need to wrap error as external error because err is already categorized by validArraySlabSerialization().
   522  			return err
   523  		}
   524  	}
   525  
   526  	return nil
   527  }
   528  
   529  func arrayDataSlabEqual(
   530  	expected *ArrayDataSlab,
   531  	actual *ArrayDataSlab,
   532  	storage SlabStorage,
   533  	cborDecMode cbor.DecMode,
   534  	cborEncMode cbor.EncMode,
   535  	decodeStorable StorableDecoder,
   536  	decodeTypeInfo TypeInfoDecoder,
   537  	compare StorableComparator,
   538  ) error {
   539  
   540  	// Compare extra data
   541  	err := arrayExtraDataEqual(expected.extraData, actual.extraData)
   542  	if err != nil {
   543  		// Don't need to wrap error as external error because err is already categorized by arrayExtraDataEqual().
   544  		return err
   545  	}
   546  
   547  	// Compare next
   548  	if expected.next != actual.next {
   549  		return NewFatalError(fmt.Errorf("next %d is wrong, want %d", actual.next, expected.next))
   550  	}
   551  
   552  	// Compare header
   553  	if !reflect.DeepEqual(expected.header, actual.header) {
   554  		return NewFatalError(fmt.Errorf("header %+v is wrong, want %+v", actual.header, expected.header))
   555  	}
   556  
   557  	// Compare elements length
   558  	if len(expected.elements) != len(actual.elements) {
   559  		return NewFatalError(fmt.Errorf("elements len %d is wrong, want %d", len(actual.elements), len(expected.elements)))
   560  	}
   561  
   562  	// Compare element
   563  	for i := 0; i < len(expected.elements); i++ {
   564  		ee := expected.elements[i]
   565  		ae := actual.elements[i]
   566  		if !compare(ee, ae) {
   567  			return NewFatalError(fmt.Errorf("element %d %+v is wrong, want %+v", i, ae, ee))
   568  		}
   569  
   570  		// Compare nested element
   571  		if idStorable, ok := ee.(StorageIDStorable); ok {
   572  
   573  			ev, err := idStorable.StoredValue(storage)
   574  			if err != nil {
   575  				// Don't need to wrap error as external error because err is already categorized by StorageIDStorable.StoredValue().
   576  				return err
   577  			}
   578  
   579  			return ValidValueSerialization(
   580  				ev,
   581  				cborDecMode,
   582  				cborEncMode,
   583  				decodeStorable,
   584  				decodeTypeInfo,
   585  				compare,
   586  			)
   587  		}
   588  	}
   589  
   590  	return nil
   591  }
   592  
   593  func arrayMetaDataSlabEqual(expected, actual *ArrayMetaDataSlab) error {
   594  
   595  	// Compare extra data
   596  	err := arrayExtraDataEqual(expected.extraData, actual.extraData)
   597  	if err != nil {
   598  		// Don't need to wrap error as external error because err is already categorized by arrayExtraDataEqual().
   599  		return err
   600  	}
   601  
   602  	// Compare header
   603  	if !reflect.DeepEqual(expected.header, actual.header) {
   604  		return NewFatalError(fmt.Errorf("header %+v is wrong, want %+v", actual.header, expected.header))
   605  	}
   606  
   607  	// Compare childrenHeaders
   608  	if !reflect.DeepEqual(expected.childrenHeaders, actual.childrenHeaders) {
   609  		return NewFatalError(fmt.Errorf("childrenHeaders %+v is wrong, want %+v", actual.childrenHeaders, expected.childrenHeaders))
   610  	}
   611  
   612  	// Compare childrenCountSum
   613  	if !reflect.DeepEqual(expected.childrenCountSum, actual.childrenCountSum) {
   614  		return NewFatalError(fmt.Errorf("childrenCountSum %+v is wrong, want %+v", actual.childrenCountSum, expected.childrenCountSum))
   615  	}
   616  
   617  	return nil
   618  }
   619  
   620  func arrayExtraDataEqual(expected, actual *ArrayExtraData) error {
   621  
   622  	if (expected == nil) && (actual == nil) {
   623  		return nil
   624  	}
   625  
   626  	if (expected == nil) != (actual == nil) {
   627  		return NewFatalError(fmt.Errorf("has extra data is %t, want %t", actual == nil, expected == nil))
   628  	}
   629  
   630  	if !reflect.DeepEqual(*expected, *actual) {
   631  		return NewFatalError(fmt.Errorf("extra data %+v is wrong, want %+v", *actual, *expected))
   632  	}
   633  
   634  	return nil
   635  }
   636  
   637  func getEncodedArrayExtraDataSize(extraData *ArrayExtraData, cborEncMode cbor.EncMode) (int, error) {
   638  	if extraData == nil {
   639  		return 0, nil
   640  	}
   641  
   642  	var buf bytes.Buffer
   643  	enc := NewEncoder(&buf, cborEncMode)
   644  
   645  	// Normally the flag shouldn't be 0. But in this case we just need the encoded data size
   646  	// so the content of the flag doesn't matter.
   647  	err := extraData.Encode(enc, byte(0))
   648  	if err != nil {
   649  		// Don't need to wrap error as external error because err is already categorized by ArrayExtraData.Encode().
   650  		return 0, err
   651  	}
   652  
   653  	return len(buf.Bytes()), nil
   654  }
   655  
   656  func ValidValueSerialization(
   657  	value Value,
   658  	cborDecMode cbor.DecMode,
   659  	cborEncMode cbor.EncMode,
   660  	decodeStorable StorableDecoder,
   661  	decodeTypeInfo TypeInfoDecoder,
   662  	compare StorableComparator,
   663  ) error {
   664  
   665  	switch v := value.(type) {
   666  	case *Array:
   667  		return ValidArraySerialization(
   668  			v,
   669  			cborDecMode,
   670  			cborEncMode,
   671  			decodeStorable,
   672  			decodeTypeInfo,
   673  			compare,
   674  		)
   675  	case *OrderedMap:
   676  		return ValidMapSerialization(
   677  			v,
   678  			cborDecMode,
   679  			cborEncMode,
   680  			decodeStorable,
   681  			decodeTypeInfo,
   682  			compare,
   683  		)
   684  	}
   685  	return nil
   686  }