kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/serving/pipeline/encoding.go (about)

     1  /*
     2   * Copyright 2018 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package pipeline
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  
    23  	gcolumnar "kythe.io/kythe/go/serving/graph/columnar"
    24  	"kythe.io/kythe/go/serving/xrefs/columnar"
    25  	"kythe.io/kythe/go/util/kytheuri"
    26  
    27  	"github.com/apache/beam/sdks/go/pkg/beam"
    28  
    29  	cpb "kythe.io/kythe/proto/common_go_proto"
    30  	gspb "kythe.io/kythe/proto/graph_serving_go_proto"
    31  	ppb "kythe.io/kythe/proto/pipeline_go_proto"
    32  	scpb "kythe.io/kythe/proto/schema_go_proto"
    33  	srvpb "kythe.io/kythe/proto/serving_go_proto"
    34  	spb "kythe.io/kythe/proto/storage_go_proto"
    35  	xspb "kythe.io/kythe/proto/xref_serving_go_proto"
    36  )
    37  
    38  func init() {
    39  	beam.RegisterFunction(encodeCrossRef)
    40  	beam.RegisterFunction(encodeDecorPiece)
    41  	beam.RegisterFunction(encodeEdgeTarget)
    42  	beam.RegisterFunction(encodeEdges)
    43  	beam.RegisterFunction(encodeEdgesEntry)
    44  	beam.RegisterFunction(nodeToCrossRef)
    45  	beam.RegisterFunction(refToCrossRef)
    46  	beam.RegisterType(reflect.TypeOf((*gspb.Edges)(nil)).Elem())
    47  	beam.RegisterType(reflect.TypeOf((*xspb.CrossReferences)(nil)).Elem())
    48  	beam.RegisterType(reflect.TypeOf((*xspb.FileDecorations)(nil)).Elem())
    49  }
    50  
    51  func encodeCrossRef(xr *xspb.CrossReferences, emit func([]byte, []byte)) error {
    52  	kv, err := columnar.EncodeCrossReferencesEntry(columnar.CrossReferencesKeyPrefix, xr)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	emit(kv.Key, kv.Value)
    57  	return nil
    58  }
    59  
    60  func refToCrossRef(r *ppb.Reference) *xspb.CrossReferences {
    61  	ref := &xspb.CrossReferences_Reference{Location: r.Anchor}
    62  	if k := r.GetGenericKind(); k != "" {
    63  		ref.Kind = &xspb.CrossReferences_Reference_GenericKind{k}
    64  	} else {
    65  		ref.Kind = &xspb.CrossReferences_Reference_KytheKind{r.GetKytheKind()}
    66  	}
    67  	return &xspb.CrossReferences{
    68  		Source: r.Source,
    69  		Entry:  &xspb.CrossReferences_Reference_{ref},
    70  	}
    71  }
    72  
    73  func nodeToCrossRef(key *spb.VName, nodeStream func(**scpb.Node) bool, msStream func(**cpb.MarkedSource) bool) *xspb.CrossReferences {
    74  	var n *scpb.Node
    75  	var ms *cpb.MarkedSource
    76  	nodeStream(&n)
    77  	msStream(&ms)
    78  	return &xspb.CrossReferences{
    79  		Source: key,
    80  		Entry: &xspb.CrossReferences_Index_{&xspb.CrossReferences_Index{
    81  			Node:         n,
    82  			MarkedSource: ms,
    83  		}},
    84  	}
    85  }
    86  
    87  func encodeDecorPiece(file *spb.VName, p *ppb.DecorationPiece, emit func([]byte, []byte)) error {
    88  	switch p := p.Piece.(type) {
    89  	case *ppb.DecorationPiece_File:
    90  		return encodeDecorFile(file, p.File, emit)
    91  	case *ppb.DecorationPiece_Reference:
    92  		return encodeDecorRef(file, p.Reference, emit)
    93  	case *ppb.DecorationPiece_Node:
    94  		return encodeDecorNode(file, p.Node, emit)
    95  	case *ppb.DecorationPiece_Definition_:
    96  		return encodeDecorDef(file, p.Definition, emit)
    97  	case *ppb.DecorationPiece_Diagnostic:
    98  		return encodeDecorDiagnostic(file, p.Diagnostic, emit)
    99  	case *ppb.DecorationPiece_TargetOverride:
   100  		return encodeDecorTargetOverride(file, p.TargetOverride, emit)
   101  	default:
   102  		return fmt.Errorf("unknown DecorationPiece: %T", p)
   103  	}
   104  }
   105  
   106  func encodeDecorTargetOverride(file *spb.VName, o *xspb.FileDecorations_TargetOverride, emit func([]byte, []byte)) error {
   107  	e, err := columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   108  		File: file,
   109  		Entry: &xspb.FileDecorations_TargetOverride_{
   110  			TargetOverride: o,
   111  		},
   112  	})
   113  	if err != nil {
   114  		return err
   115  	}
   116  	emit(e.Key, e.Value)
   117  	return nil
   118  }
   119  
   120  func encodeDecorFile(file *spb.VName, f *srvpb.File, emit func([]byte, []byte)) error {
   121  	// Emit FileDecorations Index
   122  	e, err := columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   123  		File: file,
   124  		Entry: &xspb.FileDecorations_Index_{&xspb.FileDecorations_Index{
   125  			TextEncoding: f.Encoding,
   126  		}},
   127  	})
   128  	if err != nil {
   129  		return err
   130  	}
   131  	emit(e.Key, e.Value)
   132  
   133  	// Encode file contents as single entry
   134  	// TODO(schroederc): chunk large file contents
   135  	e, err = columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   136  		File: file,
   137  		Entry: &xspb.FileDecorations_Text_{&xspb.FileDecorations_Text{
   138  			StartOffset: 0,
   139  			EndOffset:   int32(len(f.Text)),
   140  			Text:        f.Text,
   141  		}},
   142  	})
   143  	if err != nil {
   144  		return err
   145  	}
   146  	emit(e.Key, e.Value)
   147  	return nil
   148  }
   149  
   150  func encodeDecorRef(file *spb.VName, ref *ppb.Reference, emit func([]byte, []byte)) error {
   151  	target := &xspb.FileDecorations_Target{
   152  		StartOffset: ref.Anchor.Span.Start.ByteOffset,
   153  		EndOffset:   ref.Anchor.Span.End.ByteOffset,
   154  		BuildConfig: ref.Anchor.BuildConfiguration,
   155  		Target:      ref.Source,
   156  	}
   157  	if k := ref.GetGenericKind(); k != "" {
   158  		target.Kind = &xspb.FileDecorations_Target_GenericKind{k}
   159  	} else {
   160  		target.Kind = &xspb.FileDecorations_Target_KytheKind{ref.GetKytheKind()}
   161  	}
   162  	e, err := columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   163  		File:  file,
   164  		Entry: &xspb.FileDecorations_Target_{target},
   165  	})
   166  	if err != nil {
   167  		return err
   168  	}
   169  	emit(e.Key, e.Value)
   170  	return nil
   171  }
   172  
   173  func encodeDecorNode(file *spb.VName, node *scpb.Node, emit func([]byte, []byte)) error {
   174  	e, err := columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   175  		File: file,
   176  		Entry: &xspb.FileDecorations_TargetNode_{&xspb.FileDecorations_TargetNode{
   177  			Node: node,
   178  		}},
   179  	})
   180  	if err != nil {
   181  		return err
   182  	}
   183  	emit(e.Key, e.Value)
   184  	return nil
   185  }
   186  
   187  func encodeDecorDef(file *spb.VName, def *ppb.DecorationPiece_Definition, emit func([]byte, []byte)) error {
   188  	// TODO(schroederc): use VNames throughout pipeline
   189  	defVName, err := kytheuri.ToVName(def.Definition.Ticket)
   190  	if err != nil {
   191  		return err
   192  	}
   193  	e, err := columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   194  		File: file,
   195  		Entry: &xspb.FileDecorations_TargetDefinition_{&xspb.FileDecorations_TargetDefinition{
   196  			Target:     def.Node,
   197  			Definition: defVName,
   198  		}},
   199  	})
   200  	if err != nil {
   201  		return err
   202  	}
   203  	emit(e.Key, e.Value)
   204  
   205  	e, err = columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   206  		File: file,
   207  		Entry: &xspb.FileDecorations_DefinitionLocation_{&xspb.FileDecorations_DefinitionLocation{
   208  			Location: def.Definition,
   209  		}},
   210  	})
   211  	if err != nil {
   212  		return err
   213  	}
   214  	emit(e.Key, e.Value)
   215  	return nil
   216  }
   217  
   218  func encodeDecorDiagnostic(file *spb.VName, d *cpb.Diagnostic, emit func([]byte, []byte)) error {
   219  	e, err := columnar.EncodeDecorationsEntry(columnar.DecorationsKeyPrefix, &xspb.FileDecorations{
   220  		File: file,
   221  		Entry: &xspb.FileDecorations_Diagnostic_{&xspb.FileDecorations_Diagnostic{
   222  			Diagnostic: d,
   223  		}},
   224  	})
   225  	if err != nil {
   226  		return err
   227  	}
   228  	emit(e.Key, e.Value)
   229  	return nil
   230  }
   231  
   232  func encodeEdgesEntry(e *gspb.Edges, emit func([]byte, []byte)) error {
   233  	kv, err := gcolumnar.EncodeEdgesEntry(gcolumnar.EdgesKeyPrefix, e)
   234  	if err != nil {
   235  		return err
   236  	}
   237  	emit(kv.Key, kv.Value)
   238  	return nil
   239  }
   240  
   241  func encodeEdgeTarget(src *spb.VName, nodeStream func(**scpb.Node) bool, targetStream func(**spb.VName) bool, emit func(*gspb.Edges)) {
   242  	var node *scpb.Node
   243  	if !nodeStream(&node) {
   244  		node = &scpb.Node{}
   245  	} else {
   246  		node = nodeWithoutEdges(node)
   247  	}
   248  	node.Source = src
   249  
   250  	var target *spb.VName
   251  	for targetStream(&target) {
   252  		emit(&gspb.Edges{
   253  			Source: target,
   254  			Entry: &gspb.Edges_Target_{&gspb.Edges_Target{
   255  				Node: node,
   256  			}},
   257  		})
   258  	}
   259  }
   260  
   261  func encodeEdges(n *scpb.Node, emit func(*gspb.Edges)) error {
   262  	for _, e := range n.Edge {
   263  		edge := &gspb.Edges_Edge{
   264  			Target:  e.Target,
   265  			Ordinal: e.Ordinal,
   266  		}
   267  		if k := e.GetGenericKind(); k != "" {
   268  			edge.Kind = &gspb.Edges_Edge_GenericKind{k}
   269  		} else {
   270  			edge.Kind = &gspb.Edges_Edge_KytheKind{e.GetKytheKind()}
   271  		}
   272  		emit(&gspb.Edges{
   273  			Source: n.Source,
   274  			Entry:  &gspb.Edges_Edge_{edge},
   275  		})
   276  		emit(&gspb.Edges{
   277  			Source: e.Target,
   278  			Entry: &gspb.Edges_Edge_{&gspb.Edges_Edge{
   279  				Target:  n.Source,
   280  				Kind:    edge.Kind,
   281  				Ordinal: e.Ordinal,
   282  				Reverse: true,
   283  			}},
   284  		})
   285  	}
   286  	return nil
   287  }