def decode(self, tpe: Type[Maybe], data: Json) -> Either[JsonError, Maybe[A]]: inner = Lists.wrap(tpe.__args__).head return (Right(Nothing) if data.absent else maybe_from_object( data, inner) if data.object else decode.match(data) / Just if data.array else Right(Nothing) if data.null else inner.cata( lambda a: decode_json_type_json(data, a) / Just, lambda: data.scalar.e(f'invalid type for `Maybe`: {data}', Maybe.check(data.data))))
def either_from_object(data: JsonObject, ltype: Type[A], rtype: Type[B]) -> Do: value = yield data.field('value') decoded = yield decode.match(value) tpe = yield data.tpe yield Right(tpe(decoded))
def maybe_from_object(data: JsonObject, inner: Maybe[Type[A]]) -> Either[JsonError, Maybe[A]]: return (decode.match(data) / Just if data.has_type else inner.traverse( lambda a: decode_json_type_json(data, a), Either))
def dec_elem(a: Json) -> Either[JsonError, A]: return decode.match(a).recover_with( lambda err: dec_tpe(a, err.error))
def decode_field(field: Field) -> Do: value = yield data.field(field.name) yield (Left(JsonError(data, f'invalid type for json: {field}')) if isinstance(field.tpe, _SpecialForm) else decode.match(value) if isinstance(field.tpe, TypeVar) else decode_field_type(field.tpe, value))
def decode(self, tpe: Type[Tuple], data: Json) -> Do: t_data = yield data.field('data') a_data = yield t_data.as_array data = yield decode.match(a_data) yield Try(tuple, data)