|
| 1 | +package schema_registry |
| 2 | + |
| 3 | +import ( |
| 4 | + "crypto/sha256" |
| 5 | + "fmt" |
| 6 | + "github.com/golang/protobuf/jsonpb" |
| 7 | + "github.com/jhump/protoreflect/desc" |
| 8 | + "google.golang.org/protobuf/reflect/protodesc" |
| 9 | + "google.golang.org/protobuf/reflect/protoreflect" |
| 10 | +) |
| 11 | + |
| 12 | +type Schema struct { |
| 13 | + descriptor protoreflect.FileDescriptor |
| 14 | + definition *desc.FileDescriptor |
| 15 | +} |
| 16 | + |
| 17 | +func NewSchema(d protoreflect.FileDescriptor) (*Schema, error) { |
| 18 | + var convert func(protoreflect.FileDescriptor, bool) (*desc.FileDescriptor, references, error) |
| 19 | + convert = func(in protoreflect.FileDescriptor, dive bool) (*desc.FileDescriptor, references, error) { |
| 20 | + fdpb := protodesc.ToFileDescriptorProto(in) |
| 21 | + imports := in.Imports() |
| 22 | + refs := make(references, 0) |
| 23 | + var deps []*desc.FileDescriptor |
| 24 | + if dive { |
| 25 | + for i := 0; i < imports.Len(); i++ { |
| 26 | + imp := imports.Get(i) |
| 27 | + dp, rs, err := convert(imp, false) |
| 28 | + if err != nil { |
| 29 | + return nil, nil, err |
| 30 | + } |
| 31 | + for _, r := range rs { |
| 32 | + refs = append(refs, r) |
| 33 | + } |
| 34 | + deps = append(deps, dp) |
| 35 | + } |
| 36 | + } |
| 37 | + fd, err := desc.CreateFileDescriptor(fdpb, deps...) |
| 38 | + return fd, refs, err |
| 39 | + } |
| 40 | + file, _, err := convert(d, true) |
| 41 | + if err != nil { |
| 42 | + return nil, fmt.Errorf("NewSchema.CreateFileDescriptor: %v", err) |
| 43 | + } |
| 44 | + return &Schema{ |
| 45 | + definition: file, |
| 46 | + descriptor: d, |
| 47 | + }, nil |
| 48 | +} |
| 49 | + |
| 50 | +func (s Schema) Fingerprint() (*Fingerprint, error) { |
| 51 | + m := &jsonpb.Marshaler{ |
| 52 | + OrigName: true, |
| 53 | + EnumsAsInts: true, |
| 54 | + EmitDefaults: false, |
| 55 | + } |
| 56 | + pb := protodesc.ToFileDescriptorProto(s.descriptor) |
| 57 | + d, err := m.MarshalToString(pb) |
| 58 | + if err != nil { |
| 59 | + return nil, err |
| 60 | + } |
| 61 | + f := Fingerprint(sha256.Sum256([]byte(d))) |
| 62 | + return &f, nil |
| 63 | +} |
| 64 | + |
| 65 | +type Fingerprint [32]byte |
| 66 | + |
| 67 | +func (f *Fingerprint) Equal(other *Fingerprint) bool { |
| 68 | + for i, b := range f { |
| 69 | + if other[i] != b { |
| 70 | + return false |
| 71 | + } |
| 72 | + } |
| 73 | + return true |
| 74 | +} |
| 75 | + |
0 commit comments