Current section

Files

Jump to
gserde src deserializer.gleam
Raw

src/deserializer.gleam

import glance
import internal/codegen/statements as gens
import internal/codegen/types as t
import gleam/string
import gleam/list
import gleam/option
import gleam/io
import gleam/int
import request.{type Request, Request}
import internal/path.{basename}
fn quote(str) {
"\"" <> str <> "\""
}
fn gen_decoder(typ) {
case typ {
glance.NamedType(name, _module_todo, parameters) -> {
case name {
"List" -> {
let assert Ok(t0) = list.at(parameters, 0)
gens.call("dynamic.list", [gen_decoder(t0)])
}
"Option" -> {
let assert Ok(t0) = list.at(parameters, 0)
gens.call("dynamic.optional", [gen_decoder(t0)])
}
_ -> gens.VarPrimitive("dynamic." <> string.lowercase(name))
}
}
glance.TupleType(parts) -> {
let m_tuple =
list.length(of: parts)
|> int.to_string
gens.call(
"dynamic.tuple" <> string.lowercase(m_tuple),
parts
|> list.map(gen_decoder),
)
}
x -> {
io.debug(#("warning: unsupported decoding", x))
gens.VarPrimitive("dynamic.toodoo")
}
}
}
fn gen_root_decoder(req) {
let Request(
src_module_name: src_module_name,
type_name: _type_name,
variant: variant,
..,
) = req
let n_str =
list.length(of: variant.fields)
|> int.to_string
gens.Function(
"from_json",
[gens.arg_typed("json_str", t.AnonymousType("String"))],
[
gens.call("json.decode", [
gens.VarPrimitive("json_str"),
gens.call("dynamic.decode" <> n_str, [
gens.VarPrimitive( basename(src_module_name) <> "." <> variant.name),
..list.map(req.variant.fields, fn(field) {
gens.call("dynamic.field", [
gens.VarPrimitive(
option.lazy_unwrap(field.label, fn() {
panic as "@todo/panic variants must be labeled"
})
|> quote,
),
gen_decoder(field.item),
])
})
]),
]),
],
)
}
pub fn to(req: Request) {
[gen_root_decoder(req)]
|> list.map(gens.generate)
|> string.join(with: "\n")
}