Skip to content

Instantly share code, notes, and snippets.

@tarao
Last active December 18, 2023 09:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tarao/2c7e5af0515ca50c09005d4cffca5724 to your computer and use it in GitHub Desktop.
Save tarao/2c7e5af0515ca50c09005d4cffca5724 to your computer and use it in GitHub Desktop.
//> using dep "com.github.tarao::record4s::0.9.1"
//> using dep "org.getshaka::native-converter::0.9.0"
import scala.compiletime.{constValue, erasedValue, summonInline}
import scala.scalajs.js
import scala.util.NotGiven
import com.github.tarao.record4s.{%, ArrayRecord, RecordLike}
import org.getshaka.nativeconverter.{NativeConverter, ParseState}
object ToNative {
private type ImplicitlyJsAny = String | Boolean | Byte | Short | Int | Float | Double | Null | js.Any
private inline def fieldsToNative[Types, Labels](
record: Map[String, Any],
res: js.Dynamic = js.Object().asInstanceOf[js.Dynamic]
): js.Any = {
inline (erasedValue[Types], erasedValue[Labels]) match {
case _: (EmptyTuple, EmptyTuple) =>
res
case _: (tpe *: types, label *: labels) =>
val labelStr = constValue[label & String]
val nativeElem =
inline erasedValue[tpe] match {
case _: ImplicitlyJsAny =>
record(labelStr).asInstanceOf[js.Any]
case _ =>
val nc = summonInline[NativeConverter[tpe]]
val elem = record(labelStr).asInstanceOf[tpe]
nc.toNative(elem)
}
res.updateDynamic(labelStr)(nativeElem)
fieldsToNative[types, labels](record, res)
}
}
inline given recordToNative[R <: %](using
r: RecordLike[R],
nonTuple: NotGiven[R <:< Tuple],
): NativeConverter[R] = {
type Types = r.ElemTypes
type Labels = r.ElemLabels
new NativeConverter[R] {
extension (record: R) {
def toNative: js.Any = fieldsToNative[Types, Labels](r.iterableOf(record).toMap)
}
def fromNative(ps: ParseState): R = ???
}
}
}
inline given arrayRecordToNative[R]: NativeConverter[ArrayRecord[R]] =
NativeConverter.derived
@main def main(): Unit = {
import ToNative.recordToNative
locally {
val r = %(name = "tarao", age = 3, email = %(local = "tarao", domain = "example.com"))
val obj = r.toNative
println(js.JSON.stringify(obj))
// {"name":"tarao","age":3,"email":{"local":"tarao","domain":"example.com"}}
}
locally {
val r = ArrayRecord(name = "tarao", age = 3, email = ArrayRecord(local = "tarao", domain = "example.com"))
val obj = r.toNative
println(js.JSON.stringify(obj))
// {"name":"tarao","age":3,"email":{"local":"tarao","domain":"example.com"}}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment