Skip to content

Commit

Permalink
wip: dto decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
pshirshov committed Oct 11, 2023
1 parent d080d33 commit f0133ac
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,8 @@ object CSBaboonTranslator {
CSType(nsLinqPkg, "JObject", fq = false)
val nsJProperty: CSType =
CSType(nsLinqPkg, "JProperty", fq = false)
val nsJTokenType: CSType =
CSType(nsLinqPkg, "JTokenType", fq = false)

val binaryReader: CSType =
CSType(ioPkg, "BinaryReader", fq = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,49 +42,181 @@ class CSNSJsonCodecGenerator(trans: CSTypeTranslator)
}
}

private def mkDecoder(tpe: TypeRef,
version: Version,
ref: TextTree[CSValue],
removeNull: Boolean,
): TextTree[CSValue] = {

def mkReader(bs: TypeId.BuiltinScalar): TextTree[CSValue] = {
val fref = if (removeNull) {
q"$ref!"
} else {
q"$ref?"
}

val out = bs match {
case TypeId.Builtins.bit =>
q"$fref.Value<Boolean>()"
case TypeId.Builtins.i08 =>
q"$fref.Value<SByte>()"
case TypeId.Builtins.i16 =>
q"$fref.Value<Int16>()"
case TypeId.Builtins.i32 =>
q"$fref.Value<Int32>()"
case TypeId.Builtins.i64 =>
q"$fref.Value<Int64>()"
case TypeId.Builtins.u08 =>
q"$fref.Value<Byte>()"
case TypeId.Builtins.u16 =>
q"$fref.Value<UInt16>()"
case TypeId.Builtins.u32 =>
q"$fref.Value<UInt32>()"
case TypeId.Builtins.u64 =>
q"$fref.Value<UInt64>()"
case TypeId.Builtins.f32 =>
q"$fref.Value<Single>()"
case TypeId.Builtins.f64 =>
q"$fref.Value<Double>()"
case TypeId.Builtins.f128 =>
q"$fref.Value<Decimal>()"
case TypeId.Builtins.str =>
q"$fref.Value<String>()"
case TypeId.Builtins.tsu =>
q"$fref.Value<DateTime>()"
case TypeId.Builtins.tso =>
q"$fref.Value<DateTime>()"
case o =>
throw new RuntimeException(s"BUG: Unexpected type: $o")
}

if (removeNull) {
q"$out!"
} else {
out
}
}

def decodeKey(tpe: TypeRef, ref: TextTree[CSValue]): TextTree[CSValue] = {
tpe.id match {
case TypeId.Builtins.bit =>
q"Boolean.Parse($ref)"
case TypeId.Builtins.i08 =>
q"SByte.Parse($ref)"
case TypeId.Builtins.i16 =>
q"Int16.Parse($ref)"
case TypeId.Builtins.i32 =>
q"Int32.Parse($ref)"
case TypeId.Builtins.i64 =>
q"Int64.Parse($ref)"
case TypeId.Builtins.u08 =>
q"Byte.Parse($ref)"
case TypeId.Builtins.u16 =>
q"UInt16.Parse($ref)"
case TypeId.Builtins.u32 =>
q"UInt32.Parse($ref)"
case TypeId.Builtins.u64 =>
q"UInt64.Parse($ref)"
case TypeId.Builtins.f32 =>
q"Single.Parse($ref)"
case TypeId.Builtins.f64 =>
q"Double.Parse($ref)"
case TypeId.Builtins.f128 =>
q"Decimal.Parse($ref)"
case TypeId.Builtins.str =>
ref
case TypeId.Builtins.tsu =>
q"DateTime.Parse($ref)"
case TypeId.Builtins.tso =>
q"DateTime.Parse($ref)"
case o =>
throw new RuntimeException(s"BUG: Unexpected type: $o")
}
}

tpe match {
case TypeRef.Scalar(id) =>
id match {
case bs: TypeId.BuiltinScalar =>
mkReader(bs)
case u: TypeId.User =>
val targetTpe = trans.toCsVal(u, version)
q"""${targetTpe}_JsonCodec.Instance.Decode($ref!)"""
}
case TypeRef.Constructor(id, args) =>
id match {
case TypeId.Builtins.opt =>
q"""$ref!.Type == $nsJTokenType.Null ? null : ${mkDecoder(
args.head,
version,
ref,
removeNull = false
)}"""

case TypeId.Builtins.map =>
q"""$ref!.Value<$nsJObject>()!.Properties().Select(kv => $csKeyValuePair.Create(${decodeKey(
args.head,
q"kv.Name"
)}, ${mkDecoder(args.last, version, q"kv.Value", removeNull = true)})).ToImmutableDictionary()"""

case TypeId.Builtins.lst =>
q"""$ref!.Value<$nsJArray>()!.Select(e => ${mkDecoder(
args.head,
version,
q"e",
removeNull = true
)}).ToImmutableList()"""
case TypeId.Builtins.set =>
q"""$ref!.Value<$nsJArray>()!.Select(e => ${mkDecoder(
args.head,
version,
q"e",
removeNull = true
)}).ToImmutableHashSet()"""
case o =>
// q"null"
throw new RuntimeException(s"BUG: Unexpected type: $o")

}
}

}

override def translate(defn: DomainMember.User,
name: CSValue.CSType,
version: Version,
): TextTree[CSValue] = {

/*
bs match {
case bit =>
case i08 =>
case i16 =>
case i32 =>
case i64 =>
case u08 =>
case u16 =>
case u32 =>
case u64 =>
case f32 =>
case f64 =>
case f128 =>
case str =>
case tsu =>
case tso =>
}
case map =>
case opt =>
case lst =>
case set =>
*/
val (enc, dec) = defn.defn match {
case d: Typedef.Dto =>
val branches = d.fields.map { f =>
val fieldRef = q"instance.${f.name.name.capitalize}"
val enc = mkEncoder(f.tpe, version, fieldRef)
val dec = mkDecoder(
f.tpe,
version,
q"""asObject["${f.name.name}"]""",
removeNull = true
)
(
q"""new $nsJProperty("${f.name.name}", $enc)""",
q"throw new NotImplementedException();"
q"${f.name.name.capitalize}: $dec",
)
}

(q"""return new $nsJObject(
|${branches.map(_._1).join(",\n").shift(4)}
|);""".stripMargin, q"throw new NotImplementedException();")
|);""".stripMargin, q"""var asObject = wire.Value<JObject>();
|
|if (asObject == null)
|{
| throw new ArgumentException($$"Cannot decode {wire} to ${name.name}: object expected");
|}
|
|return new $name(
|${branches.map(_._2).join(",\n").shift(4)}
|);
""".stripMargin)

case e: Typedef.Enum =>
val branches = e.members.toList.map { m =>
Expand All @@ -99,12 +231,12 @@ case tso =>
q"""var asStr = wire.Value<String>()?.ToLower();
|if (asStr == null)
|{
| throw new ${csArgumentException}($$"Cannot convert {wire} to ${name.name}: string expected");
| throw new ${csArgumentException}($$"Cannot decode {wire} to ${name.name}: string expected");
|}
|
|${branches.join("\n")}
|
|throw new ${csArgumentException}($$"Cannot convert {wire} to ${name.name}: no matching value");""".stripMargin
|throw new ${csArgumentException}($$"Cannot decode {wire} to ${name.name}: no matching value");""".stripMargin
)

case a: Typedef.Adt =>
Expand All @@ -129,13 +261,13 @@ case tso =>
""".stripMargin, q"""var asObject = wire.Value<JObject>();
|if (asObject == null)
|{
| throw new ArgumentException($$"Cannot convert {wire} to ${name.name}: object expected");
| throw new ArgumentException($$"Cannot decode {wire} to ${name.name}: object expected");
|}
|var head = asObject.Properties().First();
|
|${branches.map(_._2).join("\n")}
|
|throw new ArgumentException($$"Cannot convert {wire} to ${name.name}: no matching value");
|throw new ArgumentException($$"Cannot decode {wire} to ${name.name}: no matching value");
""".stripMargin)

}
Expand Down

0 comments on commit f0133ac

Please sign in to comment.