blob: 8ceeec4c37f1bed742f4ea9e2f2d6a9162fd16a5 [file] [log] [blame] [edit]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package summarize
import (
"encoding/json"
"errors"
"fmt"
"io"
"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
)
// Strictness describes if an element is strict or flexible:
// https://fuchsia.dev/fuchsia-src/reference/fidl/language/language#strict-vs-flexible
type Strictness string
const (
isStrict Strictness = "strict"
isFlexible Strictness = "flexible"
)
// Resourceness describes if an element is a value or resource type:
// https://fuchsia.dev/fuchsia-src/reference/fidl/language/language#value-vs-resource
type Resourceness string
const (
// isValue is the default, so we omit it altogether.
isValue Resourceness = ""
// isResource means the type is allowed to contain handles.
isResource Resourceness = "resource"
)
// Openness describes if a protocol is closed, ajar, or open:
// https://fuchsia.dev/fuchsia-src/reference/fidl/language/language#unknown-interactions
type Openness string
const (
isClosed Openness = "closed"
isAjar Openness = "ajar"
isOpen Openness = "open"
)
// Transport describes the transport over which a protocol is defined.
// https://fuchsia.dev/fuchsia-src/reference/fidl/language/attributes#transport
type Transport string
const (
channelTransport Transport = "channel"
driverTransport Transport = "driver"
banjoTransport Transport = "banjo"
syscallTransport Transport = "syscall"
)
// Kind corresponds to fidl::Element::Kind in fidlc, e.g. const, enum,
// enum member, struct, struct member, protocol, method, etc.
type Kind string
// Kind constants.
const (
AliasKind Kind = "alias"
BitsKind Kind = "bits"
BitsMemberKind Kind = "bits/member"
ConstKind Kind = "const"
EnumKind Kind = "enum"
EnumMemberKind Kind = "enum/member"
LibraryKind Kind = "library"
ProtocolKind Kind = "protocol"
ProtocolMemberKind Kind = "protocol/member"
StructKind Kind = "struct"
StructMemberKind Kind = "struct/member"
TableKind Kind = "table"
TableMemberKind Kind = "table/member"
UnionKind Kind = "union"
UnionMemberKind Kind = "union/member"
)
// Type is the FIDL type of an element. For enums and bits, this is the
// underlying primitive type.
type Type string
// Name is the fully qualified name of the element:
// https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0043_documentation_comment_format?hl=en#fully-qualified-names
type Name string
// Value is a string-serialized value of the element, applicable to consts,
// enum/bits members, and struct members (default values).
type Value string
// Ordinal is the ordinal of a method, or of a struct, table, or union member.
// It is a string to allow the full uint64 range in JSON. For struct members,
// which have no explicit ordinals in FIDL source, it is a one-based index.
type Ordinal string
// Direction indicates if a method is one-way, two-way, or an event.
type Direction string
const (
isOneWay Direction = "one_way"
isTwoWay Direction = "two_way"
isEvent Direction = "event"
)
// fidlConstToValue converts the fidlgen view of a constant value to
// summary's Value.
func fidlConstToValue(fc *fidlgen.Constant) Value {
if fc == nil {
return Value("")
}
// It looks like any value type has its value in fc.Value.
return Value(fc.Value)
}
// ElementStr is a generic stringly-typed view of an Element. The aim is to keep
// the structure as flat as possible, and omit fields which have no bearing to
// the Kind of element represented.
type ElementStr struct {
Kind `json:"kind"`
Name `json:"name"`
Strictness `json:"strictness,omitempty"`
Resourceness `json:"resourceness,omitempty"`
Ordinal `json:"ordinal,omitempty"`
Type `json:"type,omitempty"`
Value `json:"value,omitempty"`
// Protocols only
Openness `json:"openness,omitempty"`
Transport `json:"transport,omitempty"`
// Methods only
Direction `json:"direction,omitempty"`
Request Type `json:"request,omitempty"`
Response Type `json:"response,omitempty"`
Error Type `json:"error,omitempty"`
}
func (e ElementStr) Less(other ElementStr) bool {
n1 := newFqn(Name(e.Name))
n2 := newFqn(Name(other.Name))
return n1.Less(n2)
}
// IsStrict returns true of this element is strict. The result makes sense only
// on elements that have a defined strictness.
func (e ElementStr) IsStrict() bool {
// Tables are always flexible
if e.Kind == TableKind {
return false
}
// Structs are always strict
if e.Kind == StructKind {
return true
}
// Some types are optionally strict.
return e.Strictness == isStrict
}
// HasStrictness returns true if this ElementStr's FIDL kind has a notion of strictness.
//
// See https://fuchsia.dev/fuchsia-src/reference/fidl/language/language?hl=en#strict-vs-flexible.
func (e ElementStr) HasStrictness() bool {
switch e.Kind {
case BitsKind, EnumKind, UnionKind, StructKind, TableKind:
return true
default:
return false
}
}
// LoadSummariesJSON loads several the API summaries in the JSON format from
// the given reader readers. Returns the respective summaries in the order of
// supplied readers, or the first encountered error.
func LoadSummariesJSON(rs ...io.Reader) ([][]ElementStr, error) {
var rets [][]ElementStr
for _, r := range rs {
ret := []ElementStr{}
d := json.NewDecoder(r)
err := d.Decode(&ret)
if err != nil && !errors.Is(err, io.EOF) {
return nil, fmt.Errorf("while decoding the summary: %w", err)
}
rets = append(rets, ret)
}
return rets, nil
}