Skip to content

Commit

Permalink
added SQL type overrides, #32
Browse files Browse the repository at this point in the history
added Ilk as a supertype of all DataTypes,
added DataType.NotNull as a supertype for Simple, Collect, and Partial
  • Loading branch information
Miha-x64 committed May 24, 2020
1 parent aade0a4 commit 01bd583
Show file tree
Hide file tree
Showing 40 changed files with 1,131 additions and 746 deletions.
Expand Up @@ -36,7 +36,7 @@ fun <T> JsonReader.readListOf(type: DataType<T>): Nothing =
/**
* Reads a JSON value denoted by [type] as [T].
*
* For [Schema]s and [DataType.Partial]s,
* For [Schema]s and [DataType.NotNull.Partial]s,
* this ignores key-value pairs not listed in schema,
* and consumes both opening and closing curly braces.
* Throws an exception if there was no value for any [FieldDef] without a default value,
Expand Down
Expand Up @@ -30,7 +30,7 @@ internal fun <T> DataType<T>.get(prefs: SharedPreferences, name: String, default
* we store 'null' ourselves. If a field has String type, 'null' is stored as Boolean 'false'.
* Otherwise 'null' is stored as a String "null".
*/
@JvmSynthetic internal val storedAsString = DataType.Simple.Kind.Str + DataType.Simple.Kind.Blob
@JvmSynthetic internal val storedAsString = DataType.NotNull.Simple.Kind.Str + DataType.NotNull.Simple.Kind.Blob

@Suppress("UNCHECKED_CAST")
private fun <T> DataType<T>.get(prefs: SharedPreferences, key: String): T {
Expand All @@ -45,35 +45,35 @@ private fun <T> DataType<T>.get(prefs: SharedPreferences, key: String): T {
val act = actualType
when (act) {
is DataType.Nullable<*, *> -> throw AssertionError()
is DataType.Simple<*> -> if (value == (if (act.kind in storedAsString) false else "null")) return null as T
is DataType.Collect<*, *, *>, is DataType.Partial<*, *> -> if (value == false) return null as T
is DataType.NotNull.Simple<*> -> if (value == (if (act.kind in storedAsString) false else "null")) return null as T
is DataType.NotNull.Collect<*, *, *>, is DataType.NotNull.Partial<*, *> -> if (value == false) return null as T
}
act as DataType<T/*!!*/>
} else this

return when (type) {
is DataType.Nullable<*, *> -> throw AssertionError()
is DataType.Simple -> type.load(
is DataType.NotNull.Simple -> type.load(
if (type.hasStringRepresentation) value as CharSequence
else when (type.kind) {
DataType.Simple.Kind.Bool -> value as Boolean
DataType.Simple.Kind.I32 -> value as Int
DataType.Simple.Kind.I64 -> value as Long
DataType.Simple.Kind.F32 -> value as Float
DataType.Simple.Kind.F64 -> JavaLangDouble.longBitsToDouble(value as Long)
DataType.Simple.Kind.Str -> value as String
DataType.Simple.Kind.Blob -> Base64.decode(value as String, Base64.DEFAULT)
DataType.NotNull.Simple.Kind.Bool -> value as Boolean
DataType.NotNull.Simple.Kind.I32 -> value as Int
DataType.NotNull.Simple.Kind.I64 -> value as Long
DataType.NotNull.Simple.Kind.F32 -> value as Float
DataType.NotNull.Simple.Kind.F64 -> JavaLangDouble.longBitsToDouble(value as Long)
DataType.NotNull.Simple.Kind.Str -> value as String
DataType.NotNull.Simple.Kind.Blob -> Base64.decode(value as String, Base64.DEFAULT)
else -> throw AssertionError()
}
)
is DataType.Collect<T, *, *> -> type.elementType.let { elementType ->
if (elementType is DataType.Simple<*> &&
(elementType.hasStringRepresentation || elementType.kind == DataType.Simple.Kind.Str)) // TODO should store everything in strings
is DataType.NotNull.Collect<T, *, *> -> type.elementType.let { elementType ->
if (elementType is DataType.NotNull.Simple<*> &&
(elementType.hasStringRepresentation || elementType.kind == DataType.NotNull.Simple.Kind.Str)) // TODO should store everything in strings
type.load((value as Set<String>).map(elementType::load)) // todo zero-copy
else /* here we have a Collection<Whatever>, including potentially a collection of collections, structs, etc */
serialized(type).load(Base64.decode(value as String, Base64.DEFAULT))
}
is DataType.Partial<*, *> -> serialized(type).load(Base64.decode(value as String, Base64.DEFAULT))
is DataType.NotNull.Partial<*, *> -> serialized(type).load(Base64.decode(value as String, Base64.DEFAULT))
}
}

Expand All @@ -83,11 +83,11 @@ internal fun <T> DataType<T>.put(editor: SharedPreferences.Editor, key: String,
if (value == null) when (act) {
is DataType.Nullable<*, *> ->
throw AssertionError()
is DataType.Simple<*> ->
is DataType.NotNull.Simple<*> ->
if (act.kind in storedAsString) editor.putBoolean(key, false) else editor.putString(key, "null")
is DataType.Collect<*, *, *> ->
is DataType.NotNull.Collect<*, *, *> ->
editor.putBoolean(key, false)
is DataType.Partial<*, *> ->
is DataType.NotNull.Partial<*, *> ->
editor.putBoolean(key, false)
}.also { return }

Expand All @@ -96,33 +96,33 @@ internal fun <T> DataType<T>.put(editor: SharedPreferences.Editor, key: String,

when (type) {
is DataType.Nullable<*, *> -> throw AssertionError()
is DataType.Simple<T> ->
is DataType.NotNull.Simple<T> ->
if (type.hasStringRepresentation) editor.putString(key, type.storeAsString(value).toString())
else type.store(value).let { v -> when (type.kind) {
DataType.Simple.Kind.Bool -> editor.putBoolean(key, v as Boolean)
DataType.Simple.Kind.I32 -> editor.putInt(key, v as Int)
DataType.Simple.Kind.I64 -> editor.putLong(key, v as Long)
DataType.Simple.Kind.F32 -> editor.putFloat(key, v as Float)
DataType.Simple.Kind.F64 -> editor.putLong(key, java.lang.Double.doubleToLongBits(v as Double))
DataType.Simple.Kind.Str -> editor.putString(key, v as String)
DataType.Simple.Kind.Blob -> editor.putString(key, Base64.encodeToString(v as ByteArray, Base64.DEFAULT))
DataType.NotNull.Simple.Kind.Bool -> editor.putBoolean(key, v as Boolean)
DataType.NotNull.Simple.Kind.I32 -> editor.putInt(key, v as Int)
DataType.NotNull.Simple.Kind.I64 -> editor.putLong(key, v as Long)
DataType.NotNull.Simple.Kind.F32 -> editor.putFloat(key, v as Float)
DataType.NotNull.Simple.Kind.F64 -> editor.putLong(key, java.lang.Double.doubleToLongBits(v as Double))
DataType.NotNull.Simple.Kind.Str -> editor.putString(key, v as String)
DataType.NotNull.Simple.Kind.Blob -> editor.putString(key, Base64.encodeToString(v as ByteArray, Base64.DEFAULT))
else -> throw AssertionError()
} }
is DataType.Collect<T, *, *> -> type.elementType.let { elementType ->
if (elementType is DataType.Simple && (elementType.hasStringRepresentation || elementType.kind == DataType.Simple.Kind.Str))
is DataType.NotNull.Collect<T, *, *> -> type.elementType.let { elementType ->
if (elementType is DataType.NotNull.Simple && (elementType.hasStringRepresentation || elementType.kind == DataType.NotNull.Simple.Kind.Str))
editor.putStringSet(
key,
type.store(value)
.fatMapTo<HashSet<String>, T, String>(HashSet()) { v ->
(elementType as DataType.Simple<T>)
(elementType as DataType.NotNull.Simple<T>)
.let { if (it.hasStringRepresentation) it.storeAsString(v) else it.store(v) as CharSequence }
.toString()
}
)
else
editor.putString(key, Base64.encodeToString(serialized(type).store(value) as ByteArray, Base64.DEFAULT))
}
is DataType.Partial<*, *> ->
is DataType.NotNull.Partial<*, *> ->
editor.putString(key, Base64.encodeToString(serialized(type).store(value) as ByteArray, Base64.DEFAULT))
}
}
Expand Up @@ -2,6 +2,6 @@ package net.aquadc.persistence.extended

import net.aquadc.persistence.type.DataType

abstract class StringableSimpleType<T> internal constructor(kind: Kind) : DataType.Simple<T>(kind) {
internal abstract class StringableSimpleType<T>(kind: Kind) : DataType.NotNull.Simple<T>(kind) {
final override val hasStringRepresentation: Boolean get() = true
}
Expand Up @@ -19,7 +19,7 @@ import net.aquadc.persistence.type.DataType

private class EitherType<A, B, C, D, E, F, G, H, SCH : Schema<SCH>>(
schema: SCH
) : DataType.Partial<Either8<A, B, C, D, E, F, G, H>, SCH>(schema) {
) : DataType.NotNull.Partial<Either8<A, B, C, D, E, F, G, H>, SCH>(schema) {

override fun load(fields: FieldSet<SCH, FieldDef<SCH, *, *>>, values: Any?): Either8<A, B, C, D, E, F, G, H> =
when (schema.single(fields).ordinal.toInt()) {
Expand All @@ -46,27 +46,27 @@ private class EitherType<A, B, C, D, E, F, G, H, SCH : Schema<SCH>>(
fun <A, DA : DataType<A>, B, DB : DataType<B>> either(
firstName: String, firstType: DA,
secondName: String, secondType: DB
): DataType.Partial<Either<A, B>, Tuple<A, DA, B, DB>> =
): DataType.NotNull.Partial<Either<A, B>, Tuple<A, DA, B, DB>> =
EitherType(Tuple(firstName, firstType, secondName, secondType))

@JvmSynthetic // useless for Java
operator fun <A, DA : DataType<A>, B, DB : DataType<B>>
DA.plus(second: DB): DataType.Partial<Either<A, B>, Tuple<A, DA, B, DB>> =
DA.plus(second: DB): DataType.NotNull.Partial<Either<A, B>, Tuple<A, DA, B, DB>> =
either("first", this, "second", second)


fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>> either3(
firstName: String, firstType: DA,
secondName: String, secondType: DB,
thirdName: String, thirdType: DC
): DataType.Partial<Either3<A, B, C>, Tuple3<A, DA, B, DB, C, DC>> =
): DataType.NotNull.Partial<Either3<A, B, C>, Tuple3<A, DA, B, DB, C, DC>> =
EitherType(Tuple3(
firstName, firstType, secondName, secondType, thirdName, thirdType
))

@JvmSynthetic // useless for Java
operator fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>>
DataType.Partial<Either<A, B>, Tuple<A, DA, B, DB>>.plus(third: DC): DataType.Partial<Either3<A, B, C>, Tuple3<A, DA, B, DB, C, DC>> =
DataType.NotNull.Partial<Either<A, B>, Tuple<A, DA, B, DB>>.plus(third: DC): DataType.NotNull.Partial<Either3<A, B, C>, Tuple3<A, DA, B, DB, C, DC>> =
either3("first", schema.run { First.type }, "second", schema.run { Second.type }, "third", third)


Expand All @@ -75,14 +75,14 @@ fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : Data
secondName: String, secondType: DB,
thirdName: String, thirdType: DC,
fourthName: String, fourthType: DD
): DataType.Partial<Either4<A, B, C, D>, Tuple4<A, DA, B, DB, C, DC, D, DD>> =
): DataType.NotNull.Partial<Either4<A, B, C, D>, Tuple4<A, DA, B, DB, C, DC, D, DD>> =
EitherType(Tuple4(
firstName, firstType, secondName, secondType, thirdName, thirdType, fourthName, fourthType
))

@JvmSynthetic // useless for Java
@JvmName("e3plus") operator fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : DataType<D>>
DataType.Partial<Either3<A, B, C>, Tuple3<A, DA, B, DB, C, DC>>.plus(fourth: DD): DataType.Partial<Either4<A, B, C, D>, Tuple4<A, DA, B, DB, C, DC, D, DD>> =
DataType.NotNull.Partial<Either3<A, B, C>, Tuple3<A, DA, B, DB, C, DC>>.plus(fourth: DD): DataType.NotNull.Partial<Either4<A, B, C, D>, Tuple4<A, DA, B, DB, C, DC, D, DD>> =
either4("first", schema.run { First.type }, "second", schema.run { Second.type }, "third", schema.run { Third.type }, "fourth", fourth)


Expand All @@ -92,15 +92,15 @@ fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : Data
thirdName: String, thirdType: DC,
fourthName: String, fourthType: DD,
fifthName: String, fifthType: DE
): DataType.Partial<Either5<A, B, C, D, E>, Tuple5<A, DA, B, DB, C, DC, D, DD, E, DE>> =
): DataType.NotNull.Partial<Either5<A, B, C, D, E>, Tuple5<A, DA, B, DB, C, DC, D, DD, E, DE>> =
EitherType(Tuple5(
firstName, firstType, secondName, secondType, thirdName, thirdType, fourthName, fourthType,
fifthName, fifthType
))

@JvmSynthetic // useless for Java
@JvmName("e4plus") operator fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : DataType<D>, E, DE : DataType<E>>
DataType.Partial<Either4<A, B, C, D>, Tuple4<A, DA, B, DB, C, DC, D, DD>>.plus(fifth: DE): DataType.Partial<Either5<A, B, C, D, E>, Tuple5<A, DA, B, DB, C, DC, D, DD, E, DE>> =
DataType.NotNull.Partial<Either4<A, B, C, D>, Tuple4<A, DA, B, DB, C, DC, D, DD>>.plus(fifth: DE): DataType.NotNull.Partial<Either5<A, B, C, D, E>, Tuple5<A, DA, B, DB, C, DC, D, DD, E, DE>> =
either5("first", schema.run { First.type }, "second", schema.run { Second.type }, "third", schema.run { Third.type }, "fourth", schema.run { Fourth.type }, "fifth", fifth)


Expand All @@ -111,15 +111,15 @@ fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : Data
fourthName: String, fourthType: DD,
fifthName: String, fifthType: DE,
sixthName: String, sixthType: DF
): DataType.Partial<Either6<A, B, C, D, E, F>, Tuple6<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF>> =
): DataType.NotNull.Partial<Either6<A, B, C, D, E, F>, Tuple6<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF>> =
EitherType(Tuple6(
firstName, firstType, secondName, secondType, thirdName, thirdType, fourthName, fourthType,
fifthName, fifthType, sixthName, sixthType
))

@JvmSynthetic // useless for Java
@JvmName("e5plus") operator fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : DataType<D>, E, DE : DataType<E>, F, DF : DataType<F>>
DataType.Partial<Either5<A, B, C, D, E>, Tuple5<A, DA, B, DB, C, DC, D, DD, E, DE>>.plus(sixth: DF): DataType.Partial<Either6<A, B, C, D, E, F>, Tuple6<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF>> =
DataType.NotNull.Partial<Either5<A, B, C, D, E>, Tuple5<A, DA, B, DB, C, DC, D, DD, E, DE>>.plus(sixth: DF): DataType.NotNull.Partial<Either6<A, B, C, D, E, F>, Tuple6<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF>> =
either6("first", schema.run { First.type }, "second", schema.run { Second.type }, "third", schema.run { Third.type }, "fourth", schema.run { Fourth.type }, "fifth", schema.run { Fifth.type }, "sixth", sixth)


Expand All @@ -131,15 +131,15 @@ fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : Data
fifthName: String, fifthType: DE,
sixthName: String, sixthType: DF,
seventhName: String, seventhType: DG
): DataType.Partial<Either7<A, B, C, D, E, F, G>, Tuple7<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG>> =
): DataType.NotNull.Partial<Either7<A, B, C, D, E, F, G>, Tuple7<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG>> =
EitherType(Tuple7(
firstName, firstType, secondName, secondType, thirdName, thirdType, fourthName, fourthType,
fifthName, fifthType, sixthName, sixthType, seventhName, seventhType
))

@JvmSynthetic // useless for Java
@JvmName("e6plus") operator fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : DataType<D>, E, DE : DataType<E>, F, DF : DataType<F>, G, DG : DataType<G>>
DataType.Partial<Either6<A, B, C, D, E, F>, Tuple6<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF>>.plus(seventh: DG): DataType.Partial<Either7<A, B, C, D, E, F, G>, Tuple7<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG>> =
DataType.NotNull.Partial<Either6<A, B, C, D, E, F>, Tuple6<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF>>.plus(seventh: DG): DataType.NotNull.Partial<Either7<A, B, C, D, E, F, G>, Tuple7<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG>> =
either7("first", schema.run { First.type }, "second", schema.run { Second.type }, "third", schema.run { Third.type }, "fourth", schema.run { Fourth.type }, "fifth", schema.run { Fifth.type }, "sixth", schema.run { Sixth.type }, "seventh", seventh)


Expand All @@ -152,15 +152,15 @@ fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : Data
sixthName: String, sixthType: DF,
seventhName: String, seventhType: DG,
eighthName: String, eighthType: DH
): DataType.Partial<Either8<A, B, C, D, E, F, G, H>, Tuple8<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG, H, DH>> =
): DataType.NotNull.Partial<Either8<A, B, C, D, E, F, G, H>, Tuple8<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG, H, DH>> =
EitherType(Tuple8(
firstName, firstType, secondName, secondType, thirdName, thirdType, fourthName, fourthType,
fifthName, fifthType, sixthName, sixthType, seventhName, seventhType, eighthName, eighthType
))

@JvmSynthetic // useless for Java
@JvmName("e7plus") operator fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : DataType<D>, E, DE : DataType<E>, F, DF : DataType<F>, G, DG : DataType<G>, H, DH : DataType<H>>
DataType.Partial<Either7<A, B, C, D, E, F, G>, Tuple7<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG>>.plus(eighth: DH): DataType.Partial<Either8<A, B, C, D, E, F, G, H>, Tuple8<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG, H, DH>> =
DataType.NotNull.Partial<Either7<A, B, C, D, E, F, G>, Tuple7<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG>>.plus(eighth: DH): DataType.NotNull.Partial<Either8<A, B, C, D, E, F, G, H>, Tuple8<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG, H, DH>> =
either8("first", schema.run { First.type }, "second", schema.run { Second.type }, "third", schema.run { Third.type }, "fourth", schema.run { Fourth.type }, "fifth", schema.run { Fifth.type }, "sixth", schema.run { Sixth.type }, "seventh", schema.run { Seventh.type }, "eighth", eighth)


Expand All @@ -170,7 +170,7 @@ fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : Data
*/
@JvmSynthetic // useless for Java
@JvmName("e8plus") @Deprecated("Either9+ are not implemented", level = DeprecationLevel.ERROR) operator fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : DataType<D>, E, DE : DataType<E>, F, DF : DataType<F>, G, DG : DataType<G>, H, DH : DataType<H>, I, DI : DataType<I>>
DataType.Partial<Either8<A, B, C, D, E, F, G, H>, Tuple8<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG, H, DH>>.plus(ninth: DI): Nothing =
DataType.NotNull.Partial<Either8<A, B, C, D, E, F, G, H>, Tuple8<A, DA, B, DB, C, DC, D, DD, E, DE, F, DF, G, DG, H, DH>>.plus(ninth: DI): Nothing =
throw UnsupportedOperationException()

/**
Expand All @@ -179,6 +179,6 @@ fun <A, DA : DataType<A>, B, DB : DataType<B>, C, DC : DataType<C>, D, DD : Data
*/
@JvmSynthetic // useless for Java
@JvmName("plusE") @Deprecated("right operand is not expected to be Either", level = DeprecationLevel.ERROR) operator fun
DataType.Partial<out Either8<*, *, *, *, *, *, *, *>, out Tuple8<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>>
.plus(other: DataType.Partial<out Either8<*, *, *, *, *, *, *, *>, out Tuple8<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>>): Nothing =
DataType.NotNull.Partial<out Either8<*, *, *, *, *, *, *, *>, out Tuple8<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>>
.plus(other: DataType.NotNull.Partial<out Either8<*, *, *, *, *, *, *, *>, out Tuple8<*, *, *, *, *, *, *, *, *, *, *, *, *, *, *, *>>): Nothing =
throw UnsupportedOperationException()
Expand Up @@ -9,7 +9,7 @@ import net.aquadc.persistence.type.SimpleValue
* Represents AARRGGBB colour as an [Int].
* For text formats, uses #AARRGGBB; when alpha==FF, uses #RRGGBB.
*/
val colour: DataType.Simple<Int> = object : StringableSimpleType<Int>(Kind.I32) {
val colour: DataType.NotNull.Simple<Int> = object : StringableSimpleType<Int>(Kind.I32) {
override fun load(value: SimpleValue): Int =
if (value is CharSequence) parse(value) else value as Int
override fun store(value: Int): SimpleValue = value
Expand Down

0 comments on commit 01bd583

Please sign in to comment.