Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve external types and JSON codec #2401

Merged
merged 17 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 68 additions & 64 deletions encoding/json/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,28 +111,30 @@ func (d *Decoder) Decode() (value cadence.Value, err error) {
}

const (
typeKey = "type"
kindKey = "kind"
valueKey = "value"
keyKey = "key"
nameKey = "name"
fieldsKey = "fields"
initializersKey = "initializers"
idKey = "id"
targetPathKey = "targetPath"
borrowTypeKey = "borrowType"
domainKey = "domain"
identifierKey = "identifier"
staticTypeKey = "staticType"
addressKey = "address"
pathKey = "path"
authorizedKey = "authorized"
sizeKey = "size"
typeIDKey = "typeID"
restrictionsKey = "restrictions"
labelKey = "label"
parametersKey = "parameters"
returnKey = "return"
typeKey = "type"
kindKey = "kind"
valueKey = "value"
keyKey = "key"
nameKey = "name"
fieldsKey = "fields"
initializersKey = "initializers"
idKey = "id"
targetPathKey = "targetPath"
borrowTypeKey = "borrowType"
domainKey = "domain"
identifierKey = "identifier"
staticTypeKey = "staticType"
addressKey = "address"
pathKey = "path"
authorizedKey = "authorized"
sizeKey = "size"
typeIDKey = "typeID"
restrictionsKey = "restrictions"
labelKey = "label"
parametersKey = "parameters"
typeParametersKey = "typeParameters"
returnKey = "return"
typeBoundKey = "typeBound"
)

func (d *Decoder) decodeJSON(v any) cadence.Value {
Expand Down Expand Up @@ -215,8 +217,6 @@ func (d *Decoder) decodeJSON(v any) cadence.Value {
return d.decodeEvent(valueJSON)
case contractTypeStr:
return d.decodeContract(valueJSON)
case linkTypeStr:
return d.decodeLink(valueJSON)
case pathTypeStr:
return d.decodePath(valueJSON)
case typeTypeStr:
Expand Down Expand Up @@ -823,29 +823,6 @@ func (d *Decoder) decodeEnum(valueJSON any) cadence.Enum {
))
}

func (d *Decoder) decodeLink(valueJSON any) cadence.PathLink {
obj := toObject(valueJSON)

targetPath, ok := d.decodeJSON(obj.Get(targetPathKey)).(cadence.Path)
if !ok {
panic(errors.NewDefaultUserError("invalid link: missing or invalid target path"))
}

borrowType := obj.GetString(borrowTypeKey)

common.UseMemory(d.gauge, common.MemoryUsage{
Kind: common.MemoryKindRawString,
// no need to add 1 to account for empty string: string is metered in Link struct
Amount: uint64(len(borrowType)),
})

return cadence.NewMeteredLink(
d.gauge,
targetPath,
borrowType,
)
}

func (d *Decoder) decodePath(valueJSON any) cadence.Path {
obj := toObject(valueJSON)

Expand All @@ -871,25 +848,54 @@ func (d *Decoder) decodePath(valueJSON any) cadence.Path {
)
}

func (d *Decoder) decodeParamType(valueJSON any, results typeDecodingResults) cadence.Parameter {
func (d *Decoder) decodeTypeParameter(valueJSON any, results typeDecodingResults) cadence.TypeParameter {
obj := toObject(valueJSON)
// Unmetered because decodeTypeParameter is metered in decodeTypeParameters and called nowhere else
typeBoundObj, ok := obj[typeBoundKey]
var typeBound cadence.Type
if ok {
typeBound = d.decodeType(typeBoundObj, results)
}

return cadence.NewTypeParameter(
toString(obj.Get(nameKey)),
typeBound,
)
}

func (d *Decoder) decodeTypeParameters(typeParams []any, results typeDecodingResults) []cadence.TypeParameter {
common.UseMemory(d.gauge, common.MemoryUsage{
Kind: common.MemoryKindCadenceTypeParameter,
Amount: uint64(len(typeParams)),
})
typeParameters := make([]cadence.TypeParameter, 0, len(typeParams))

for _, param := range typeParams {
typeParameters = append(typeParameters, d.decodeTypeParameter(param, results))
}

return typeParameters
}

func (d *Decoder) decodeParameter(valueJSON any, results typeDecodingResults) cadence.Parameter {
obj := toObject(valueJSON)
// Unmetered because decodeParamType is metered in decodeParamTypes and called nowhere else
// Unmetered because decodeParameter is metered in decodeParameters and called nowhere else
return cadence.NewParameter(
toString(obj.Get(labelKey)),
toString(obj.Get(idKey)),
d.decodeType(obj.Get(typeKey), results),
)
}

func (d *Decoder) decodeParamTypes(params []any, results typeDecodingResults) []cadence.Parameter {
func (d *Decoder) decodeParameters(params []any, results typeDecodingResults) []cadence.Parameter {
common.UseMemory(d.gauge, common.MemoryUsage{
Kind: common.MemoryKindCadenceParameter,
Amount: uint64(len(params)),
})
parameters := make([]cadence.Parameter, 0, len(params))

for _, param := range params {
parameters = append(parameters, d.decodeParamType(param, results))
parameters = append(parameters, d.decodeParameter(param, results))
}

return parameters
Expand Down Expand Up @@ -919,16 +925,17 @@ func (d *Decoder) decodeFieldType(valueJSON any, results typeDecodingResults) ca
)
}

func (d *Decoder) decodeFunctionType(returnValue, parametersValue, id any, results typeDecodingResults) cadence.Type {
parameters := d.decodeParamTypes(toSlice(parametersValue), results)
func (d *Decoder) decodeFunctionType(typeParametersValue, parametersValue, returnValue any, results typeDecodingResults) cadence.Type {
typeParameters := d.decodeTypeParameters(toSlice(typeParametersValue), results)
parameters := d.decodeParameters(toSlice(parametersValue), results)
returnType := d.decodeType(returnValue, results)

return cadence.NewMeteredFunctionType(
d.gauge,
"",
typeParameters,
parameters,
returnType,
).WithID(toString(id))
)
}

func (d *Decoder) decodeNominalType(
Expand All @@ -943,7 +950,7 @@ func (d *Decoder) decodeNominalType(
for _, params := range initializers {
inits = append(
inits,
d.decodeParamTypes(toSlice(params), results),
d.decodeParameters(toSlice(params), results),
)
}

Expand Down Expand Up @@ -1051,21 +1058,20 @@ func (d *Decoder) decodeNominalType(
func (d *Decoder) decodeRestrictedType(
typeValue any,
restrictionsValue []any,
typeIDValue string,
results typeDecodingResults,
) cadence.Type {
typ := d.decodeType(typeValue, results)

restrictions := make([]cadence.Type, 0, len(restrictionsValue))
for _, restriction := range restrictionsValue {
restrictions = append(restrictions, d.decodeType(restriction, results))
}

return cadence.NewMeteredRestrictedType(
d.gauge,
"",
typ,
restrictions,
).WithID(typeIDValue)
)
}

type typeDecodingResults map[string]cadence.Type
Expand All @@ -1092,18 +1098,16 @@ func (d *Decoder) decodeType(valueJSON any, results typeDecodingResults) cadence

switch kindValue {
case "Function":
returnValue := obj.Get(returnKey)
typeParametersValue := obj.Get(typeParametersKey)
parametersValue := obj.Get(parametersKey)
idValue := obj.Get(typeIDKey)
return d.decodeFunctionType(returnValue, parametersValue, idValue, results)
returnValue := obj.Get(returnKey)
return d.decodeFunctionType(typeParametersValue, parametersValue, returnValue, results)
case "Restriction":
restrictionsValue := obj.Get(restrictionsKey)
typeIDValue := toString(obj.Get(typeIDKey))
typeValue := obj.Get(typeKey)
return d.decodeRestrictedType(
typeValue,
toSlice(restrictionsValue),
typeIDValue,
results,
)
case "Optional":
Expand Down
Loading