encodeFirestoreValue function
Encodes a document body for the native side.
Plain Dart values map to their CBOR equivalents; FirestoreValue instances become tagged items.
Implementation
CborValue encodeFirestoreValue(Object? v) {
if (v == null) return const CborNull();
if (v is bool) return CborBool(v);
if (v is int) return CborInt(BigInt.from(v));
if (v is double) return CborFloat(v);
if (v is String) return CborString(v);
if (v is Uint8List) return CborBytes(v);
if (v is FirestoreTimestamp) {
return CborList(
[CborInt(BigInt.from(v.seconds)), CborInt(BigInt.from(v.nanoseconds))],
tags: [FirestoreTag.timestamp],
);
}
if (v is FirestoreGeoPoint) {
return CborList(
[CborFloat(v.latitude), CborFloat(v.longitude)],
tags: [FirestoreTag.geoPoint],
);
}
if (v is FirestoreReference) {
return CborString(v.path, tags: [FirestoreTag.reference]);
}
if (v is FirestoreSentinel) {
final payload = v._payload;
return switch (v._tag) {
FirestoreTag.arrayUnion || FirestoreTag.arrayRemove => CborList(
(payload! as List<Object?>).map(encodeFirestoreValue).toList(),
tags: [v._tag],
),
// A one-element array, not a bare number: the cbor package drops tags
// when it normalizes an integer to a small int, so a tagged bare int
// arrives untagged and would decode as an ordinary value.
FirestoreTag.incrementInt => CborList(
[CborInt(BigInt.from(payload! as int))],
tags: [v._tag],
),
FirestoreTag.incrementDouble => CborList(
[CborFloat((payload! as num).toDouble())],
tags: [v._tag],
),
_ => CborNull(tags: [v._tag]),
};
}
if (v is List) return CborList(v.map(encodeFirestoreValue).toList());
if (v is Map) {
return CborMap({
for (final e in v.entries)
CborString('${e.key}'): encodeFirestoreValue(e.value),
});
}
throw ArgumentError.value(v, 'value', 'no Firestore mapping for this type');
}