kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/serving/graph/columnar/columnar_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 src 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 columnar implements the columnar table format for a Kythe xrefs service.
    18  package columnar // import "kythe.io/kythe/go/serving/graph/columnar"
    19  
    20  import (
    21  	"fmt"
    22  
    23  	"kythe.io/kythe/go/util/keys"
    24  
    25  	"google.golang.org/protobuf/proto"
    26  
    27  	gspb "kythe.io/kythe/proto/graph_serving_go_proto"
    28  	scpb "kythe.io/kythe/proto/schema_go_proto"
    29  	spb "kythe.io/kythe/proto/storage_go_proto"
    30  )
    31  
    32  var (
    33  	// EdgesKeyPrefix is the common key prefix for all Kythe columnar Edges
    34  	// key-value entries.
    35  	EdgesKeyPrefix, _ = keys.Append(nil, "eg")
    36  )
    37  
    38  func init() {
    39  	// Restrict the capacity of the key prefix to ensure appending to it creates a new array.
    40  	EdgesKeyPrefix = EdgesKeyPrefix[:len(EdgesKeyPrefix):len(EdgesKeyPrefix)]
    41  }
    42  
    43  // Columnar edges group numbers.
    44  // See: kythe/proto/graph_serving.proto
    45  const (
    46  	columnarEdgesIndexGroup  = -1 // no group number
    47  	columnarEdgesEdgeGroup   = 10
    48  	columnarEdgesTargetGroup = 20
    49  )
    50  
    51  // KV is a single columnar key-value entry.
    52  type KV struct{ Key, Value []byte }
    53  
    54  // EncodeEdgesEntry encodes a columnar Edges entry.
    55  func EncodeEdgesEntry(keyPrefix []byte, eg *gspb.Edges) (*KV, error) {
    56  	switch e := eg.Entry.(type) {
    57  	case *gspb.Edges_Index_:
    58  		return encodeEdgesIndex(keyPrefix, eg.Source, e.Index)
    59  	case *gspb.Edges_Edge_:
    60  		return encodeEdge(keyPrefix, eg.Source, e.Edge)
    61  	case *gspb.Edges_Target_:
    62  		return encodeEdgesTarget(keyPrefix, eg.Source, e.Target)
    63  	default:
    64  		return nil, fmt.Errorf("unknown Edges entry: %T", e)
    65  	}
    66  }
    67  
    68  func encodeEdgesIndex(prefix []byte, src *spb.VName, idx *gspb.Edges_Index) (*KV, error) {
    69  	key, err := keys.Append(prefix, src)
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  	val, err := proto.Marshal(idx)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return &KV{key, val}, nil
    78  }
    79  
    80  func encodeEdge(prefix []byte, src *spb.VName, e *gspb.Edges_Edge) (*KV, error) {
    81  	key, err := keys.Append(prefix, src, columnarEdgesEdgeGroup,
    82  		e.GetGenericKind(), int32(e.GetKytheKind()), e.Ordinal, e.Reverse, e.Target)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	val, err := proto.Marshal(&gspb.Edges_Edge{})
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	return &KV{key, val}, nil
    91  }
    92  
    93  func encodeEdgesTarget(prefix []byte, src *spb.VName, t *gspb.Edges_Target) (*KV, error) {
    94  	key, err := keys.Append(prefix, src, columnarEdgesTargetGroup, t.Node.Source)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	val, err := proto.Marshal(t)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	return &KV{key, val}, nil
   103  }
   104  
   105  // DecodeEdgesEntry decodes a columnar Edges entry.
   106  func DecodeEdgesEntry(src *spb.VName, key string, val []byte) (*gspb.Edges, error) {
   107  	kind := columnarEdgesIndexGroup
   108  	if key != "" {
   109  		var err error
   110  		key, err = keys.Parse(key, &kind)
   111  		if err != nil {
   112  			return nil, fmt.Errorf("invalid Edges group kind: %v", err)
   113  		}
   114  	}
   115  	switch kind {
   116  	case columnarEdgesIndexGroup:
   117  		return decodeEdgesIndex(src, key, val)
   118  	case columnarEdgesEdgeGroup:
   119  		return decodeEdge(src, key, val)
   120  	case columnarEdgesTargetGroup:
   121  		return decodeEdgesTarget(src, key, val)
   122  	default:
   123  		return nil, fmt.Errorf("unknown group kind: %d", kind)
   124  	}
   125  }
   126  
   127  func decodeEdgesIndex(src *spb.VName, key string, val []byte) (*gspb.Edges, error) {
   128  	var idx gspb.Edges_Index
   129  	if err := proto.Unmarshal(val, &idx); err != nil {
   130  		return nil, err
   131  	}
   132  	return &gspb.Edges{
   133  		Source: src,
   134  		Entry:  &gspb.Edges_Index_{&idx},
   135  	}, nil
   136  }
   137  
   138  func decodeEdge(src *spb.VName, key string, val []byte) (*gspb.Edges, error) {
   139  	var (
   140  		genericKind string
   141  		kytheKind   int32
   142  		ordinal     int32
   143  		reverse     bool
   144  		target      spb.VName
   145  	)
   146  	key, err := keys.Parse(key, &genericKind, &kytheKind, &ordinal, &reverse, &target)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	var e gspb.Edges_Edge
   151  	if err := proto.Unmarshal(val, &e); err != nil {
   152  		return nil, err
   153  	}
   154  	e.Reverse = reverse
   155  	e.Ordinal = ordinal
   156  	e.Target = &target
   157  	if genericKind != "" {
   158  		e.Kind = &gspb.Edges_Edge_GenericKind{genericKind}
   159  	} else {
   160  		e.Kind = &gspb.Edges_Edge_KytheKind{scpb.EdgeKind(kytheKind)}
   161  	}
   162  	return &gspb.Edges{
   163  		Source: src,
   164  		Entry:  &gspb.Edges_Edge_{&e},
   165  	}, nil
   166  }
   167  
   168  func decodeEdgesTarget(src *spb.VName, key string, val []byte) (*gspb.Edges, error) {
   169  	var tgt gspb.Edges_Target
   170  	if err := proto.Unmarshal(val, &tgt); err != nil {
   171  		return nil, err
   172  	}
   173  	return &gspb.Edges{
   174  		Source: src,
   175  		Entry:  &gspb.Edges_Target_{&tgt},
   176  	}, nil
   177  }