drift/moor/lib/src/runtime/data_class.dart

104 lines
2.9 KiB
Dart

import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:moor/moor.dart';
/// Common interface for objects which can be inserted or updated into a
/// database.
@optionalTypeArgs
abstract class Insertable<D extends DataClass> {
/// Used internally by moor.
T createCompanion<T extends UpdateCompanion<D>>(bool nullToAbsent);
}
/// A common supertype for all data classes generated by moor. Data classes are
/// immutable structures that represent a single row in a database table.
abstract class DataClass {
const DataClass();
/// Converts this object into a representation that can be encoded with
/// [json]. The [serializer] can be used to configure how individual values
/// will be encoded.
Map<String, dynamic> toJson(
{ValueSerializer serializer = const ValueSerializer.defaults()});
/// Converts this object into a json representation. The [serializer] can be
/// used to configure how individual values will be encoded.
String toJsonString(
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
return json.encode(toJson(serializer: serializer));
}
/// Used internally be generated code
@protected
static dynamic parseJson(String jsonString) {
return json.decode(jsonString);
}
}
/// An update companion for a [DataClass] which is used to write data into a
/// database using [InsertStatement.insert] or [UpdateStatement.write].
///
/// See also:
/// - the explanation in the changelog for 1.5
/// - https://github.com/simolus3/moor/issues/25
abstract class UpdateCompanion<D extends DataClass> implements Insertable<D> {
const UpdateCompanion();
@override
T createCompanion<T extends UpdateCompanion<D>>(bool nullToAbsent) {
return this as T;
}
}
/// A wrapper around arbitrary data [T] to indicate presence or absence
/// explicitly.
class Value<T> {
final bool present;
final T value;
const Value.use(this.value) : present = true;
const Value.absent()
: value = null,
present = false;
}
/// Serializer responsible for mapping atomic types from and to json.
abstract class ValueSerializer {
const ValueSerializer();
/// The default serializer encodes date times as a unix-timestamp in
/// milliseconds.
const factory ValueSerializer.defaults() = _DefaultValueSerializer;
/// Converts the [value] to something that can be passed to
/// [JsonCodec.encode].
dynamic toJson<T>(T value);
/// Inverse of [toJson]: Converts a value obtained from [JsonCodec.decode]
/// into a value that can be hold by data classes.
T fromJson<T>(dynamic json);
}
class _DefaultValueSerializer extends ValueSerializer {
const _DefaultValueSerializer();
@override
T fromJson<T>(json) {
if (T == DateTime) {
return DateTime.fromMillisecondsSinceEpoch(json as int) as T;
}
return json as T;
}
@override
dynamic toJson<T>(T value) {
if (value is DateTime) {
return value.millisecondsSinceEpoch;
}
return value;
}
}