DocumentSnapshot<T>.fromUpdateMap constructor

DocumentSnapshot<T>.fromUpdateMap(
  1. DocumentReference<T> ref,
  2. UpdateMap data
)

Implementation

factory DocumentSnapshot.fromUpdateMap(
  DocumentReference<T> ref,
  UpdateMap data,
) {
  final serializer = ref.firestore._serializer;

  /// Merges 'value' at the field path specified by the path array into
  /// 'target'.
  ApiMapValue? merge({
    required ApiMapValue target,
    required Object? value,
    required List<String> path,
    required int pos,
  }) {
    final key = path[pos];
    final isLast = pos == path.length - 1;

    if (!target.containsKey(key)) {
      if (isLast) {
        if (value is _FieldTransform) {
          // If there is already data at this path, we need to retain it.
          // Otherwise, we don't include it in the DocumentSnapshot.
          return target.isNotEmpty ? target : null;
        }
        // The merge is done
        final leafNode = serializer.encodeValue(value);
        if (leafNode != null) {
          target[key] = leafNode;
        }
        return target;
      } else {
        // We need to expand the target object.
        final childNode = <String, firestore1.Value>{};

        final nestedValue = merge(
          target: childNode,
          value: value,
          path: path,
          pos: pos + 1,
        );

        if (nestedValue != null) {
          target[key] = firestore1.Value(
            mapValue: firestore1.MapValue(fields: nestedValue),
          );
          return target;
        } else {
          return target.isNotEmpty ? target : null;
        }
      }
    } else {
      assert(!isLast, "Can't merge current value into a nested object");
      target[key] = firestore1.Value(
        mapValue: firestore1.MapValue(
          fields: merge(
            target: target[key]!.mapValue!.fields!,
            value: value,
            path: path,
            pos: pos + 1,
          ),
        ),
      );
      return target;
    }
  }

  final res = <String, firestore1.Value>{};
  for (final entry in data.entries) {
    final path = entry.key._toList();
    merge(target: res, value: entry.value, path: path, pos: 0);
  }

  return DocumentSnapshot._(
    ref: ref,
    fieldsProto: firestore1.MapValue(fields: res),
    readTime: null,
    createTime: null,
    updateTime: null,
  );
}