github.com/onflow/atree@v0.6.0/storable_slab.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  // StorableSlab allows storing storables (CBOR encoded data) directly in a slab.
    22  // Eventually we will only have a dictionary at the account storage root,
    23  // so this won't be needed, but during the refactor we have the need to store
    24  // other non-dictionary values (e.g. strings, integers, etc.) directly in accounts
    25  // (i.e. directly in slabs aka registers)
    26  type StorableSlab struct {
    27  	StorageID StorageID
    28  	Storable  Storable
    29  }
    30  
    31  var _ Slab = StorableSlab{}
    32  
    33  func (s StorableSlab) ChildStorables() []Storable {
    34  	return []Storable{s.Storable}
    35  }
    36  
    37  func (s StorableSlab) Encode(enc *Encoder) error {
    38  	// Encode version
    39  	enc.Scratch[0] = 0
    40  
    41  	// Encode flag
    42  	flag := maskStorable
    43  	flag = setNoSizeLimit(flag)
    44  
    45  	if _, ok := s.Storable.(StorageIDStorable); ok {
    46  		flag = setHasPointers(flag)
    47  	}
    48  
    49  	enc.Scratch[1] = flag
    50  
    51  	_, err := enc.Write(enc.Scratch[:versionAndFlagSize])
    52  	if err != nil {
    53  		return NewEncodingError(err)
    54  	}
    55  
    56  	err = s.Storable.Encode(enc)
    57  	if err != nil {
    58  		// Wrap err as external error (if needed) because err is returned by Storable interface.
    59  		return wrapErrorfAsExternalErrorIfNeeded(err, "failed to encode storable")
    60  	}
    61  
    62  	return nil
    63  }
    64  
    65  func (s StorableSlab) ByteSize() uint32 {
    66  	return versionAndFlagSize + s.Storable.ByteSize()
    67  }
    68  
    69  func (s StorableSlab) ID() StorageID {
    70  	return s.StorageID
    71  }
    72  
    73  func (s StorableSlab) StoredValue(storage SlabStorage) (Value, error) {
    74  	value, err := s.Storable.StoredValue(storage)
    75  	if err != nil {
    76  		// Wrap err as external error (if needed) because err is returned by Storable interface.
    77  		return nil, wrapErrorfAsExternalErrorIfNeeded(err, "failed to get storable's stored value")
    78  	}
    79  	return value, nil
    80  }
    81  
    82  func (StorableSlab) Split(_ SlabStorage) (Slab, Slab, error) {
    83  	return nil, nil, NewNotApplicableError("StorableSlab", "Slab", "Split")
    84  }
    85  
    86  func (StorableSlab) Merge(_ Slab) error {
    87  	return NewNotApplicableError("StorableSlab", "Slab", "Merge")
    88  }
    89  
    90  func (StorableSlab) LendToRight(_ Slab) error {
    91  	return NewNotApplicableError("StorableSlab", "Slab", "LendToRight")
    92  }
    93  
    94  func (StorableSlab) BorrowFromRight(_ Slab) error {
    95  	return NewNotApplicableError("StorableSlab", "Slab", "BorrowFromRight")
    96  }