PB and J

(the J is for Jesse)

The "Challenge"

  • 3D in the browser
  • Scientific Data
  • Tight Deadline
  • New + Old Technology
  • Custom parser
  • Needs runtime manipulation!
  • Current speed? Send help.
  • "Browser? Can't be done."

"Its a Visualizer"

Meet Segy

SEG-Y

  • Designed for Tape
  • Endian issues
  • Standard yet Nonstandard
  • 48 years old

1

Old

  • Challenging Errors
  • Scientific Domain
  • Difficult to find clear examples
  • Software Vendors "Spec Ball of Mud" for decades

2

Opaque

Like.

Massive.

Big honkin' files.

3

Huge

Seismic Reflection Standard

No, really.

Like. Massive.

 

Budget:

  441.Million points + Metadata.

3

Huge

Trace

{
  "textHeader": {
    "C01": "  CLIENT/JOB ID    0 5 5 5 2 9 3 4 7 2",
    "C02": "  LINE  L3X",
    "C03": "  REEL NO 751023083601   DAY-START OF REEL  23       YEAR 1975",
    "C04": "  INSTRUMENT: MFG TI          MODEL AS",
    "C05": "  DATA TRACES/RECORD0001      AUXILIARY TRACES/RECORD 0       CDP FOLD  0001",
    "C06": "SAMPLE INTERNAL 0000008000 US  SAMPLES/TRACE  0751BITS/IN 1600 BYTES/SAMPLE 4",
    "C07": "  RECORDING FORMAT  STDI              FORMAT THIS REEL SEG Y1",
    "C08": "  SAMPLE CODE: FLOATING PT",
    "C09": "  GAIN TYPE:   FLOATING PT",
    "C10": "  PROCESSING:",
    "C11": "  PROCESSING:",
    "C12": "  FIELD TAPE PROCESSING MACHINE NUMBER IS:    TIMAP2",
    "C13": "  INPUT TAPE FORMAT IS :          STDI",
    "C14": "  TMIN REQUESTED THIS REEL  00000000      TMAX REQUESTED THIS REEL  00006000",
    "C15": "  INITIAL CHANNEL REQUESTED   0001    NUMBER OF CHANNELS REQUESTED  0001",
    "C16": "  DELTA 0008 MILLIVOLT LEVEL  000000  TYPE INPUT  0001",
    "C17": "  TRACE HEADER INFORMATION BY BYTE :",
    "C18": "  BYTES 181-182 : TMIN THIS TRACE         BYTES 183-184 : TMAX THIS TRACE",
    "C19": "  BYTES 185-186 : TRACE FLAG  1= GOOD     2 = MISSING OR DEAD TRACE INPUT",
    "C20": "  3= REQUESTED DUMMY TRACE                BYTES 187-188 : TDS THIS TRACE",
    "C21": "BYTES 189-192 : WATER DEPTH AT CDP    BYTES 193-196 : PRENMO DATUM CORR MS T",
    "C22": "BYTES 197-200 : POSTNMO DATUM CORR MS T",
    "C23": "BYTES 201-204 : DATUM TIME -- TIME TO WHICH TRACES HAVE BEEN CORRECTED",
    "C24": "BYTES 205-208 : DATUM VELOCITY   - TO WHICH TRACES HAVE BEEN CORRECTED",
    "C25": "BINARY TAPE HEADER IDENTIFICATION :    JOB ID -  32 BIT FIXED POINT",
    "C26": "REEL ID- 32 BIT PACKED BINARY BASE 10 BYTES 1-4 JOB ID  BYTES 5-8 REEL ID",
    "C27": "BYTES 95-96 SDOM: 0=SPC, 1= CDP",
    "C28": "END PROCESSING:                                                               "
  },
  "binaryHeader": {
    "JobID": 1110580000,
    "LineNumber": 3,
    "ReelNumber": 1110579969,
    "Traces": 1,
    "AuxTraces": 0,
    "Interval": 8000,
    "IntervalOriginal": 0,
    "Samples": 751,
    "SamplesOriginal": 0,
    "Format": 1,
    "EnsembleFold": 1,
    "SortingCode": 4,
    "VerticalSum": 1,
    "SweepFrequencyStart": 0,
    "SweepFrequencyEnd": 0,
    "SweepLength": 0,
    "Sweep": 0,
    "SweepChannel": 0,
    "SweepTaperStart": 0,
    "SweepTaperEnd": 0,
    "Taper": 0,
    "CorrelatedTraces": 0,
    "BinaryGainRecovery": 1,
    "AmplitudeRecovery": 4,
    "MeasurementSystem": 0,
    "ImpulseSignalPolarity": 0,
    "VibratoryPolarity": 0,
    "SEGY_BIN_EXT_TRACES": 4294836236,
    "ExtAuxTraces": 65536,
    "SEGY_BIN_DT": 0,
    "SEGY_BIN_NS": 0,
    "SEGY_BIN_SEGY_REVISION": 0,
    "SEGY_BIN_SEGY_REVISION_MINOR": 0,
    "SEGY_BIN_TIME_BASIS_CODE": 0,
    "SEGY_BIN_TRACE_NUMBER": 0
  },
  "dt": 0.008,
  "ns": 751,
  "traces": [
    {
      "TRACE_SEQUENCE_LINE": 1,
      "TRACE_SEQUENCE_FILE": 1,
      "FieldRecord": 11,
      "TraceNumber": 0,
      "EnergySourcePoint": 0,
      "CDP": 1,
      "CDP_TRACE": 1,
      "TraceIdentificationCode": 1,
      "NSummedTraces": 1,
      "NStackedTraces": 1,
      "DataUse": 1,
      "offset": 0,
      "ReceiverGroupElevation": 0,
      "SourceSurfaceElevation": 0,
      "SourceDepth": 0,
      "ReceiverDatumElevation": 0,
      "SourceDatumElevation": 0,
      "SourceWaterDepth": 0,
      "GroupWaterDepth": 0,
      "ElevationScalar": 1,
      "SourceGroupScalar": 1,
      "SourceX": 0,
      "SourceY": 0,
      "GroupX": 0,
      "GroupY": 0,
      "CoordinateUnits": 0,
      "WeatheringVelocity": 0,
      "SubWeatheringVelocity": 0,
      "SourceUpholeTime": 0,
      "GroupUpholeTime": 0,
      "SourceStaticCorrection": 0,
      "GroupStaticCorrection": 0,
      "TotalStaticApplied": 0,
      "LagTimeA": 0,
      "LagTimeB": 0,
      "DelayRecordingTime": 0,
      "MuteTimeStart": 0,
      "MuteTimeEND": 0,
      "TRACE_SAMPLE_COUNT": 751,
      "TRACE_SAMPLE_INTERVAL": 8000,
      "GainType": 0,
      "InstrumentGainConstant": 0,
      "InstrumentInitialGain": 0,
      "Correlated": 0,
      "SweepFrequencyStart": 0,
      "SweepFrequencyEnd": 0,
      "SweepLength": 0,
      "SweepType": 0,
      "SweepTraceTaperLengthStart": 0,
      "SweepTraceTaperLengthEnd": 0,
      "TaperType": 0,
      "AliasFilterFrequency": 0,
      "AliasFilterSlope": 0,
      "NotchFilterFrequency": 0,
      "NotchFilterSlope": 0,
      "LowCutFrequency": 0,
      "HighCutFrequency": 0,
      "LowCutSlope": 0,
      "HighCutSlope": 0,
      "YearDataRecorded": 16,
      "DayOfYear": 35,
      "HourOfDay": 8,
      "MinuteOfHour": 54,
      "SecondOfMinute": 1,
      "TimeBaseCode": 1,
      "TraceWeightingFactor": 10,
      "GeophoneGroupNumberRoll1": 0,
      "GeophoneGroupNumberFirstTraceOrigField": 0,
      "GeophoneGroupNumberLastTraceOrigField": 0,
      "GapSize": 0,
      "OverTravel": 0,
      "CDP_X": 6000,
      "CDP_Y": 65536,
      "INLINE_3D": 0,
      "CROSSLINE_3D": 0,
      "ShotPoint": 0,
      "ShotPointScalar": 0,
      "TraceValueMeasurementUnit": 84,
      "TransductionConstantMantissa": 10000,
      "TransductionConstantPower": 0,
      "TransductionUnit": 0,
      "TraceIdentifier": 0,
      "ScalarTraceHeader": 0,
      "SourceType": 0,
      "SourceEnergyDirectionMantissa": 0,
      "SourceEnergyDirectionExponent": 0,
      "SourceMeasurementMantissa": 0,
      "SourceMeasurementExponent": 0,
      "SourceMeasurementUnit": 0,
      "UnassignedInt1": 0,
      "UnassignedInt2": 0
    }
  ]
  • Headers
  • Slices (iline)
  • Traces (cdp)
  • Samples (time)

My first PB

  •  
  •  
    • InterPlanetary Linked Data
    • Codecs

goes

goes harder

vroom vroom 🔥

Protobuf popularity

Repo NPM Stars
protobuf 9,889,655 9,000
gRPC 5,069,593 3,900
tRPC 175,594 24,800
graphql 8,762,853 19,500
next 3,440,614 105,000

The Protobuf

message Boop {
  optional int32 a = 1;
}
  • Old. Like from 2001, and public in 2008

  • C++, C#, Java, Python, JavaScript, Ruby, Go, PHP, Dart

  • Node, Web (and Scala, Swift, R, Rust etc) came later

  • (aforementioned) used in IPFS

  • Binary Wire Format

Protocol Buffers.

Probufs.

PB.

(these mean the same thing)

1

3

Base 128 Varint Sorcery

convert to bytes
08 96 01

(small values use smaller bytes)

5

  • Optional Element Culling
  • Pack Repeated Items

2

4

More Shrinkage:

  • Bools
  • Enums
  • Ints
message Boop {
  optional int32 a = 1;
}
10010110 00000001
^ msb    ^ msb

How the Smooshification Happens

  • Strong Typed
    • string
    • int32
    • repeated string
    • map<string, string>
    • enum
  • Schema Driven
  • A lot like Poco/Pojo, or Prisma DSL
  • See JSON -to- Proto converter

.proto

Performance

Faster, but for who?
And how much?

 

The Claim is

up to a 6-8x increase

goos: darwin
goarch: amd64
pkg: github.com/protobuf-benchmark
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz

                               Iterations   Time/Function Call   Memory Allocation     Rate of Malloc

MarshalJSON/Small-12            2662459         441.5 ns/op           80 B/op            1 allocs/op
MarshalJSON/Medium-12           1474044         793.8 ns/op           672 B/op           2 allocs/op
MarshalJSON/Large-12            247953          4315 ns/op            5250 B/op          2 allocs/op

MarshalProto/Small-12           6676744         178.5 ns/op           48 B/op            1 allocs/op
MarshalProto/Medium-12          4704790         235.8 ns/op           288 B/op           1 allocs/op
MarshalProto/Large-12           1983378         591.9 ns/op           3072 B/op          1 allocs/op

UnMarshalJSON/Small-12          707073          2192 ns/op            240 B/op           7 allocs/op
UnMarshalJSON/Medium-12         385875          3160 ns/op            480 B/op           7 allocs/op
UnMarshalJSON/Large-12          53250           22647 ns/op           3456 B/op          7 allocs/op

UnMarshalProto/Small-12         12717336        93.67 ns/op           0 B/op             0 allocs/op
UnMarshalProto/Medium-12        11514138        102.7 ns/op           0 B/op             0 allocs/op
UnMarshalProto/Large-12         12027140        96.40 ns/op           0 B/op             0 allocs/op

Json vs Proto (marshall/unmarshall)

Json vs Proto (size in bytes)

Format Size
Protobuf 46 bytes
JSON 85 bytes
Format Time % change
Protobuf 680ns -
Microsoft JSON 743ns 👎 9% 
JSON.NET 155ns 👎 135% 

Parse Speed

Format Size
Protobuf 225ms
JSON 323ms

100 Submissions

100 Requests

(speed)

Format Size
Protobuf 31.04kb
JSON 51.97kb

100 Submissions

100 Requests

(size)

XML vs JSON, vs MsgPack, vs Protobuf

Small Data Size

Large Data Size

lower is better

Vs several other Various Serializers

lower is better

benchmarking encoding performance ...

protobuf.js (reflect) x 724,119 ops/sec ±0.69% (89 runs sampled)
protobuf.js (static) x 755,818 ops/sec ±0.63% (90 runs sampled)
JSON (string) x 499,217 ops/sec ±4.02% (89 runs sampled)
JSON (buffer) x 394,685 ops/sec ±1.75% (88 runs sampled)
google-protobuf x 376,625 ops/sec ±1.05% (89 runs sampled)


   protobuf.js (static) was fastest
  protobuf.js (reflect) was 4.2% ops/sec slower (factor 1.0)
          JSON (string) was 36.1% ops/sec slower (factor 1.6)
          JSON (buffer) was 48.4% ops/sec slower (factor 1.9)
        google-protobuf was 50.4% ops/sec slower (factor 2.0)
benchmarking encoding performance ...

protobuf.js (reflect) x 866 ops/sec ±0.68% (92 runs sampled)
JSON (string) x 2,411 ops/sec ±0.91% (94 runs sampled)
JSON (buffer) x 1,928 ops/sec ±0.85% (94 runs sampled)

          JSON (string) was fastest
          JSON (buffer) was 20.0% ops/sec slower (factor 1.2)
  protobuf.js (reflect) was 64.0% ops/sec slower (factor 2.8)

Heterogeneous Data

Just a Bunch of Strings

(wait, what?)

The Goldilocks Zone

Wins Expected

  • Segy is a lot of numbers compared to strings
  • No good way to segment/paginate
  • Offline processing is possible
  • S3 Storage likely

3 ways to integrate (in JS)

Use the js loader and load .proto at runtime

1

Import

(Full)

(Light)

(Minimal)

rewrite .protos (or generate them) as JSON and load that

2

.proto - json

Generate code via the command line in .ts or .js and load that code normally.

3

Preproccess

  "scripts": {
    "gen-ts": "pbjs segy.proto --ts segy.proto.ts"
  },
syntax = "proto3";
package segy;

message SegyHeader {
    string         textHeader   = 1;

    BinaryHeader   binaryHeader = 2;
    Stats          stats        = 3;
}

message Stats {
  double samplesDelta          = 1;
  int32  samplesPerTrace       = 2;

  int32  CDPLow                = 3;
  int32  CDPHigh               = 4;
  int32  CDPDistance           = 5;
  int32  CDPTraceLow           = 6;
  int32  CDPTraceHigh          = 7;
  int32  CDPTraceDistance      = 8;

  int32  tracesPerSlice        = 9;
  int32  slicesCount           = 10;
  int32  tracesCount           = 11;
}

message BinaryHeader {
  int32  JobID                                              = 1;
  int32  LineNumber                                         = 2;
  int32  ReelNumber                                         = 3;
  int32  Traces                                             = 4;
  int32  AuxTraces                                          = 5;
  int32  Interval                                           = 6;
  int32  IntervalOriginal                                   = 7;
  int32  Samples                                            = 8;
  int32  SamplesOriginal                                    = 9;
  int32  Format                                             = 10;
  int32  EnsembleFold                                       = 11;
  int32  SortingCode                                        = 12;
  int32  VerticalSum                                        = 13;
  int32  SweepFrequencyStart                                = 14;
  int32  SweepFrequencyEnd                                  = 15;
  int32  SweepLength                                        = 16;
  int32  Sweep                                              = 17;
  int32  SweepChannel                                       = 18;
  int32  SweepTaperStart                                    = 19;
  int32  SweepTaperEnd                                      = 20;

1

2

/* eslint-disable */
/*
This file was generated from segy.proto at 2023-03-14 14:45:34
Run `yarn generate-protobuf` in the root to update.
*/

export interface SegyHeader {
  textHeader?: string
  binaryHeader?: BinaryHeader
  stats?: Stats
}

export function encodeSegyHeader(message: SegyHeader): Uint8Array {
  let bb = popByteBuffer()
  _encodeSegyHeader(message, bb)
  return toUint8Array(bb)
}

function _encodeSegyHeader(message: SegyHeader, bb: ByteBuffer): void {
  // optional string textHeader = 1;
  let $textHeader = message.textHeader
  if ($textHeader !== undefined) {
    writeVarint32(bb, 10)
    writeString(bb, $textHeader)
  }

  // optional BinaryHeader binaryHeader = 2;
  let $binaryHeader = message.binaryHeader
  if ($binaryHeader !== undefined) {
   //...
  }

3

/* eslint-disable */
/*
This file was generated from segy.proto at 2023-03-14 14:45:34
Run `yarn generate-protobuf` in the root to update.
*/

export interface SegyHeader {
  textHeader?: string
  binaryHeader?: BinaryHeader
  stats?: Stats
}

export function encodeSegyHeader(message: SegyHeader): Uint8Array {
  let bb = popByteBuffer()
  _encodeSegyHeader(message, bb)
  return toUint8Array(bb)
}

function _encodeSegyHeader(message: SegyHeader, bb: ByteBuffer): void {
  // optional string textHeader = 1;
  let $textHeader = message.textHeader
  if ($textHeader !== undefined) {
    writeVarint32(bb, 10)
    writeString(bb, $textHeader)
  }

  // optional BinaryHeader binaryHeader = 2;
  let $binaryHeader = message.binaryHeader
  if ($binaryHeader !== undefined) {
    writeVarint32(bb, 18)
    let nested = popByteBuffer()
    _encodeBinaryHeader($binaryHeader, nested)
    writeVarint32(bb, nested.limit)
    writeByteBuffer(bb, nested)
    pushByteBuffer(nested)
  }

  // optional Stats stats = 3;
  let $stats = message.stats
  if ($stats !== undefined) {
    writeVarint32(bb, 26)
    let nested = popByteBuffer()
    _encodeStats($stats, nested)
    writeVarint32(bb, nested.limit)
    writeByteBuffer(bb, nested)
    pushByteBuffer(nested)
  }
}

export function decodeSegyHeader(binary: Uint8Array): SegyHeader {
  return _decodeSegyHeader(wrapByteBuffer(binary))
}

function _decodeSegyHeader(bb: ByteBuffer): SegyHeader {
  let message: SegyHeader = {} as any

  end_of_message: while (!isAtEnd(bb)) {
    let tag = readVarint32(bb)

    switch (tag >>> 3) {
      case 0:
        break end_of_message

      // optional string textHeader = 1;
      case 1: {
        message.textHeader = readString(bb, readVarint32(bb))
        break
      }

      // optional BinaryHeader binaryHeader = 2;
      case 2: {
        let limit = pushTemporaryLength(bb)
        message.binaryHeader = _decodeBinaryHeader(bb)
        bb.limit = limit
        break
      }

      // optional Stats stats = 3;
      case 3: {
        let limit = pushTemporaryLength(bb)
        message.stats = _decodeStats(bb)
        bb.limit = limit
        break
      }

      default:
        skipUnknownField(bb, tag & 7)
    }
  }

  return message
}

export interface Stats {
  samplesDelta?: number
  samplesPerTrace?: number
  CDPLow?: number
  CDPHigh?: number
  CDPDistance?: number
  CDPTraceLow?: number
  CDPTraceHigh?: number
  CDPTraceDistance?: number
  tracesPerSlice?: number
  slicesCount?: number
  tracesCount?: number
}

export function encodeStats(message: Stats): Uint8Array {
  let bb = popByteBuffer()
  _encodeStats(message, bb)
  return toUint8Array(bb)
}

function _encodeStats(message: Stats, bb: ByteBuffer): void {
  // optional double samplesDelta = 1;
  let $samplesDelta = message.samplesDelta
  if ($samplesDelta !== undefined) {
    writeVarint32(bb, 9)
    writeDouble(bb, $samplesDelta)
  }

  // optional int32 samplesPerTrace = 2;
  let $samplesPerTrace = message.samplesPerTrace
  if ($samplesPerTrace !== undefined) {
    writeVarint32(bb, 16)
    writeVarint64(bb, intToLong($samplesPerTrace))
  }

  // optional int32 CDPLow = 3;
  let $CDPLow = message.CDPLow
  if ($CDPLow !== undefined) {
    writeVarint32(bb, 24)
    writeVarint64(bb, intToLong($CDPLow))
  }

  // optional int32 CDPHigh = 4;
  let $CDPHigh = message.CDPHigh
  if ($CDPHigh !== undefined) {
    writeVarint32(bb, 32)
    writeVarint64(bb, intToLong($CDPHigh))
  }

  // optional int32 CDPDistance = 5;
  let $CDPDistance = message.CDPDistance
  if ($CDPDistance !== undefined) {
    writeVarint32(bb, 40)
    writeVarint64(bb, intToLong($CDPDistance))
  }

  // optional int32 CDPTraceLow = 6;
  let $CDPTraceLow = message.CDPTraceLow
  if ($CDPTraceLow !== undefined) {
    writeVarint32(bb, 48)
    writeVarint64(bb, intToLong($CDPTraceLow))
  }

  // optional int32 CDPTraceHigh = 7;
  let $CDPTraceHigh = message.CDPTraceHigh
  if ($CDPTraceHigh !== undefined) {
    writeVarint32(bb, 56)
    writeVarint64(bb, intToLong($CDPTraceHigh))
  }

  // optional int32 CDPTraceDistance = 8;
  let $CDPTraceDistance = message.CDPTraceDistance
  if ($CDPTraceDistance !== undefined) {
    writeVarint32(bb, 64)
    writeVarint64(bb, intToLong($CDPTraceDistance))
  }

  // optional int32 tracesPerSlice = 9;
  let $tracesPerSlice = message.tracesPerSlice
  if ($tracesPerSlice !== undefined) {
    writeVarint32(bb, 72)
    writeVarint64(bb, intToLong($tracesPerSlice))
  }

  // optional int32 slicesCount = 10;
  let $slicesCount = message.slicesCount
  if ($slicesCount !== undefined) {
    writeVarint32(bb, 80)
    writeVarint64(bb, intToLong($slicesCount))
  }

  // optional int32 tracesCount = 11;
  let $tracesCount = message.tracesCount
  if ($tracesCount !== undefined) {
    writeVarint32(bb, 88)
    writeVarint64(bb, intToLong($tracesCount))
  }
}

export function decodeStats(binary: Uint8Array): Stats {
  return _decodeStats(wrapByteBuffer(binary))
}

function _decodeStats(bb: ByteBuffer): Stats {
  let message: Stats = {} as any

  end_of_message: while (!isAtEnd(bb)) {
    let tag = readVarint32(bb)

    switch (tag >>> 3) {
      case 0:
        break end_of_message

      // optional double samplesDelta = 1;
      case 1: {
        message.samplesDelta = readDouble(bb)
        break
      }

      // optional int32 samplesPerTrace = 2;
      case 2: {
        message.samplesPerTrace = readVarint32(bb)
        break
      }

      // optional int32 CDPLow = 3;
      case 3: {
        message.CDPLow = readVarint32(bb)
        break
      }

      // optional int32 CDPHigh = 4;
      case 4: {
        message.CDPHigh = readVarint32(bb)
        break
      }

      // optional int32 CDPDistance = 5;
      case 5: {
        message.CDPDistance = readVarint32(bb)
        break
      }

      // optional int32 CDPTraceLow = 6;
      case 6: {
        message.CDPTraceLow = readVarint32(bb)
        break
      }

      // optional int32 CDPTraceHigh = 7;
      case 7: {
        message.CDPTraceHigh = readVarint32(bb)
        break
      }

      // optional int32 CDPTraceDistance = 8;
      case 8: {
        message.CDPTraceDistance = readVarint32(bb)
        break
      }

      // optional int32 tracesPerSlice = 9;
      case 9: {
        message.tracesPerSlice = readVarint32(bb)
        break
      }

      // optional int32 slicesCount = 10;
      case 10: {
        message.slicesCount = readVarint32(bb)
        break
      }

      // optional int32 tracesCount = 11;
      case 11: {
        message.tracesCount = readVarint32(bb)
        break
      }

      default:
        skipUnknownField(bb, tag & 7)
    }
  }

  return message
}

export interface BinaryHeader {
  JobID?: number
  LineNumber?: number
  ReelNumber?: number
  Traces?: number
  AuxTraces?: number
  Interval?: number
  IntervalOriginal?: number
  Samples?: number
  SamplesOriginal?: number
  Format?: number
  EnsembleFold?: number
  SortingCode?: number
  VerticalSum?: number
  SweepFrequencyStart?: number
  SweepFrequencyEnd?: number
  SweepLength?: number
  Sweep?: number
  SweepChannel?: number
  SweepTaperStart?: number
  SweepTaperEnd?: number
  Taper?: number
  CorrelatedTraces?: number
  BinaryGainRecovery?: number
  AmplitudeRecovery?: number
  MeasurementSystem?: number
  ImpulseSignalPolarity?: number
  VibratoryPolarity?: number
  SEGY_BIN_EXT_TRACES?: number
  SEGY_BIN_EXT_AUX_TRACES?: number
  SEGY_BIN_DT?: number
  SEGY_BIN_EXT_SAMPLES?: number
  SEGY_BIN_EXT_SAMPLE_INTERVAL?: Long
  SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG?: Long
  SEGY_BIN_EXT_SAMPLES_ORIGINAL?: number
  SEGY_BIN_EXT_ENSEMBLE_FOLD?: number
  SEGY_BIN_EXT_BYTE_ORDER_CHECK?: number
  SEGY_BIN_NS?: number
  SEGY_BIN_SEGY_REVISION_MAJOR?: number
  SEGY_BIN_SEGY_REVISION_MINOR?: number
  SEGY_BIN_FIXED_LENGTH_TRACES?: number
  SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS?: number
  SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS?: number
  SEGY_BIN_TIME_BASIS_CODE?: number
  SEGY_BIN_TRACE_NUMBER?: Long
  SEGY_BIN_BYTE_OFFSET_FOR_TRACES?: Long
  SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS?: number
}

export function encodeBinaryHeader(message: BinaryHeader): Uint8Array {
  let bb = popByteBuffer()
  _encodeBinaryHeader(message, bb)
  return toUint8Array(bb)
}

function _encodeBinaryHeader(message: BinaryHeader, bb: ByteBuffer): void {
  // optional int32 JobID = 1;
  let $JobID = message.JobID
  if ($JobID !== undefined) {
    writeVarint32(bb, 8)
    writeVarint64(bb, intToLong($JobID))
  }

  // optional int32 LineNumber = 2;
  let $LineNumber = message.LineNumber
  if ($LineNumber !== undefined) {
    writeVarint32(bb, 16)
    writeVarint64(bb, intToLong($LineNumber))
  }

  // optional int32 ReelNumber = 3;
  let $ReelNumber = message.ReelNumber
  if ($ReelNumber !== undefined) {
    writeVarint32(bb, 24)
    writeVarint64(bb, intToLong($ReelNumber))
  }

  // optional int32 Traces = 4;
  let $Traces = message.Traces
  if ($Traces !== undefined) {
    writeVarint32(bb, 32)
    writeVarint64(bb, intToLong($Traces))
  }

  // optional int32 AuxTraces = 5;
  let $AuxTraces = message.AuxTraces
  if ($AuxTraces !== undefined) {
    writeVarint32(bb, 40)
    writeVarint64(bb, intToLong($AuxTraces))
  }

  // optional int32 Interval = 6;
  let $Interval = message.Interval
  if ($Interval !== undefined) {
    writeVarint32(bb, 48)
    writeVarint64(bb, intToLong($Interval))
  }

  // optional int32 IntervalOriginal = 7;
  let $IntervalOriginal = message.IntervalOriginal
  if ($IntervalOriginal !== undefined) {
    writeVarint32(bb, 56)
    writeVarint64(bb, intToLong($IntervalOriginal))
  }

  // optional int32 Samples = 8;
  let $Samples = message.Samples
  if ($Samples !== undefined) {
    writeVarint32(bb, 64)
    writeVarint64(bb, intToLong($Samples))
  }

  // optional int32 SamplesOriginal = 9;
  let $SamplesOriginal = message.SamplesOriginal
  if ($SamplesOriginal !== undefined) {
    writeVarint32(bb, 72)
    writeVarint64(bb, intToLong($SamplesOriginal))
  }

  // optional int32 Format = 10;
  let $Format = message.Format
  if ($Format !== undefined) {
    writeVarint32(bb, 80)
    writeVarint64(bb, intToLong($Format))
  }

  // optional int32 EnsembleFold = 11;
  let $EnsembleFold = message.EnsembleFold
  if ($EnsembleFold !== undefined) {
    writeVarint32(bb, 88)
    writeVarint64(bb, intToLong($EnsembleFold))
  }

  // optional int32 SortingCode = 12;
  let $SortingCode = message.SortingCode
  if ($SortingCode !== undefined) {
    writeVarint32(bb, 96)
    writeVarint64(bb, intToLong($SortingCode))
  }

  // optional int32 VerticalSum = 13;
  let $VerticalSum = message.VerticalSum
  if ($VerticalSum !== undefined) {
    writeVarint32(bb, 104)
    writeVarint64(bb, intToLong($VerticalSum))
  }

  // optional int32 SweepFrequencyStart = 14;
  let $SweepFrequencyStart = message.SweepFrequencyStart
  if ($SweepFrequencyStart !== undefined) {
    writeVarint32(bb, 112)
    writeVarint64(bb, intToLong($SweepFrequencyStart))
  }

  // optional int32 SweepFrequencyEnd = 15;
  let $SweepFrequencyEnd = message.SweepFrequencyEnd
  if ($SweepFrequencyEnd !== undefined) {
    writeVarint32(bb, 120)
    writeVarint64(bb, intToLong($SweepFrequencyEnd))
  }

  // optional int32 SweepLength = 16;
  let $SweepLength = message.SweepLength
  if ($SweepLength !== undefined) {
    writeVarint32(bb, 128)
    writeVarint64(bb, intToLong($SweepLength))
  }

  // optional int32 Sweep = 17;
  let $Sweep = message.Sweep
  if ($Sweep !== undefined) {
    writeVarint32(bb, 136)
    writeVarint64(bb, intToLong($Sweep))
  }

  // optional int32 SweepChannel = 18;
  let $SweepChannel = message.SweepChannel
  if ($SweepChannel !== undefined) {
    writeVarint32(bb, 144)
    writeVarint64(bb, intToLong($SweepChannel))
  }

  // optional int32 SweepTaperStart = 19;
  let $SweepTaperStart = message.SweepTaperStart
  if ($SweepTaperStart !== undefined) {
    writeVarint32(bb, 152)
    writeVarint64(bb, intToLong($SweepTaperStart))
  }

  // optional int32 SweepTaperEnd = 20;
  let $SweepTaperEnd = message.SweepTaperEnd
  if ($SweepTaperEnd !== undefined) {
    writeVarint32(bb, 160)
    writeVarint64(bb, intToLong($SweepTaperEnd))
  }

  // optional int32 Taper = 21;
  let $Taper = message.Taper
  if ($Taper !== undefined) {
    writeVarint32(bb, 168)
    writeVarint64(bb, intToLong($Taper))
  }

  // optional int32 CorrelatedTraces = 22;
  let $CorrelatedTraces = message.CorrelatedTraces
  if ($CorrelatedTraces !== undefined) {
    writeVarint32(bb, 176)
    writeVarint64(bb, intToLong($CorrelatedTraces))
  }

  // optional int32 BinaryGainRecovery = 23;
  let $BinaryGainRecovery = message.BinaryGainRecovery
  if ($BinaryGainRecovery !== undefined) {
    writeVarint32(bb, 184)
    writeVarint64(bb, intToLong($BinaryGainRecovery))
  }

  // optional int32 AmplitudeRecovery = 24;
  let $AmplitudeRecovery = message.AmplitudeRecovery
  if ($AmplitudeRecovery !== undefined) {
    writeVarint32(bb, 192)
    writeVarint64(bb, intToLong($AmplitudeRecovery))
  }

  // optional int32 MeasurementSystem = 25;
  let $MeasurementSystem = message.MeasurementSystem
  if ($MeasurementSystem !== undefined) {
    writeVarint32(bb, 200)
    writeVarint64(bb, intToLong($MeasurementSystem))
  }

  // optional int32 ImpulseSignalPolarity = 26;
  let $ImpulseSignalPolarity = message.ImpulseSignalPolarity
  if ($ImpulseSignalPolarity !== undefined) {
    writeVarint32(bb, 208)
    writeVarint64(bb, intToLong($ImpulseSignalPolarity))
  }

  // optional int32 VibratoryPolarity = 27;
  let $VibratoryPolarity = message.VibratoryPolarity
  if ($VibratoryPolarity !== undefined) {
    writeVarint32(bb, 216)
    writeVarint64(bb, intToLong($VibratoryPolarity))
  }

  // optional int32 SEGY_BIN_EXT_TRACES = 28;
  let $SEGY_BIN_EXT_TRACES = message.SEGY_BIN_EXT_TRACES
  if ($SEGY_BIN_EXT_TRACES !== undefined) {
    writeVarint32(bb, 224)
    writeVarint64(bb, intToLong($SEGY_BIN_EXT_TRACES))
  }

  // optional int32 SEGY_BIN_EXT_AUX_TRACES = 29;
  let $SEGY_BIN_EXT_AUX_TRACES = message.SEGY_BIN_EXT_AUX_TRACES
  if ($SEGY_BIN_EXT_AUX_TRACES !== undefined) {
    writeVarint32(bb, 232)
    writeVarint64(bb, intToLong($SEGY_BIN_EXT_AUX_TRACES))
  }

  // optional int32 SEGY_BIN_DT = 30;
  let $SEGY_BIN_DT = message.SEGY_BIN_DT
  if ($SEGY_BIN_DT !== undefined) {
    writeVarint32(bb, 240)
    writeVarint64(bb, intToLong($SEGY_BIN_DT))
  }

  // optional int32 SEGY_BIN_EXT_SAMPLES = 31;
  let $SEGY_BIN_EXT_SAMPLES = message.SEGY_BIN_EXT_SAMPLES
  if ($SEGY_BIN_EXT_SAMPLES !== undefined) {
    writeVarint32(bb, 248)
    writeVarint64(bb, intToLong($SEGY_BIN_EXT_SAMPLES))
  }

  // optional int64 SEGY_BIN_EXT_SAMPLE_INTERVAL = 32;
  let $SEGY_BIN_EXT_SAMPLE_INTERVAL = message.SEGY_BIN_EXT_SAMPLE_INTERVAL
  if ($SEGY_BIN_EXT_SAMPLE_INTERVAL !== undefined) {
    writeVarint32(bb, 256)
    writeVarint64(bb, $SEGY_BIN_EXT_SAMPLE_INTERVAL)
  }

  // optional int64 SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG = 33;
  let $SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG = message.SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG
  if ($SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG !== undefined) {
    writeVarint32(bb, 264)
    writeVarint64(bb, $SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG)
  }

  // optional int32 SEGY_BIN_EXT_SAMPLES_ORIGINAL = 34;
  let $SEGY_BIN_EXT_SAMPLES_ORIGINAL = message.SEGY_BIN_EXT_SAMPLES_ORIGINAL
  if ($SEGY_BIN_EXT_SAMPLES_ORIGINAL !== undefined) {
    writeVarint32(bb, 272)
    writeVarint64(bb, intToLong($SEGY_BIN_EXT_SAMPLES_ORIGINAL))
  }

  // optional int32 SEGY_BIN_EXT_ENSEMBLE_FOLD = 35;
  let $SEGY_BIN_EXT_ENSEMBLE_FOLD = message.SEGY_BIN_EXT_ENSEMBLE_FOLD
  if ($SEGY_BIN_EXT_ENSEMBLE_FOLD !== undefined) {
    writeVarint32(bb, 280)
    writeVarint64(bb, intToLong($SEGY_BIN_EXT_ENSEMBLE_FOLD))
  }

  // optional int32 SEGY_BIN_EXT_BYTE_ORDER_CHECK = 36;
  let $SEGY_BIN_EXT_BYTE_ORDER_CHECK = message.SEGY_BIN_EXT_BYTE_ORDER_CHECK
  if ($SEGY_BIN_EXT_BYTE_ORDER_CHECK !== undefined) {
    writeVarint32(bb, 288)
    writeVarint64(bb, intToLong($SEGY_BIN_EXT_BYTE_ORDER_CHECK))
  }

  // optional int32 SEGY_BIN_NS = 37;
  let $SEGY_BIN_NS = message.SEGY_BIN_NS
  if ($SEGY_BIN_NS !== undefined) {
    writeVarint32(bb, 296)
    writeVarint64(bb, intToLong($SEGY_BIN_NS))
  }

  // optional int32 SEGY_BIN_SEGY_REVISION_MAJOR = 38;
  let $SEGY_BIN_SEGY_REVISION_MAJOR = message.SEGY_BIN_SEGY_REVISION_MAJOR
  if ($SEGY_BIN_SEGY_REVISION_MAJOR !== undefined) {
    writeVarint32(bb, 304)
    writeVarint64(bb, intToLong($SEGY_BIN_SEGY_REVISION_MAJOR))
  }

  // optional int32 SEGY_BIN_SEGY_REVISION_MINOR = 39;
  let $SEGY_BIN_SEGY_REVISION_MINOR = message.SEGY_BIN_SEGY_REVISION_MINOR
  if ($SEGY_BIN_SEGY_REVISION_MINOR !== undefined) {
    writeVarint32(bb, 312)
    writeVarint64(bb, intToLong($SEGY_BIN_SEGY_REVISION_MINOR))
  }

  // optional int32 SEGY_BIN_FIXED_LENGTH_TRACES = 40;
  let $SEGY_BIN_FIXED_LENGTH_TRACES = message.SEGY_BIN_FIXED_LENGTH_TRACES
  if ($SEGY_BIN_FIXED_LENGTH_TRACES !== undefined) {
    writeVarint32(bb, 320)
    writeVarint64(bb, intToLong($SEGY_BIN_FIXED_LENGTH_TRACES))
  }

  // optional int32 SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS = 41;
  let $SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS = message.SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS
  if ($SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS !== undefined) {
    writeVarint32(bb, 328)
    writeVarint64(bb, intToLong($SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS))
  }

  // optional int32 SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS = 42;
  let $SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS = message.SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS
  if ($SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS !== undefined) {
    writeVarint32(bb, 336)
    writeVarint64(bb, intToLong($SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS))
  }

  // optional int32 SEGY_BIN_TIME_BASIS_CODE = 43;
  let $SEGY_BIN_TIME_BASIS_CODE = message.SEGY_BIN_TIME_BASIS_CODE
  if ($SEGY_BIN_TIME_BASIS_CODE !== undefined) {
    writeVarint32(bb, 344)
    writeVarint64(bb, intToLong($SEGY_BIN_TIME_BASIS_CODE))
  }

  // optional uint64 SEGY_BIN_TRACE_NUMBER = 44;
  let $SEGY_BIN_TRACE_NUMBER = message.SEGY_BIN_TRACE_NUMBER
  if ($SEGY_BIN_TRACE_NUMBER !== undefined) {
    writeVarint32(bb, 352)
    writeVarint64(bb, $SEGY_BIN_TRACE_NUMBER)
  }

  // optional uint64 SEGY_BIN_BYTE_OFFSET_FOR_TRACES = 45;
  let $SEGY_BIN_BYTE_OFFSET_FOR_TRACES = message.SEGY_BIN_BYTE_OFFSET_FOR_TRACES
  if ($SEGY_BIN_BYTE_OFFSET_FOR_TRACES !== undefined) {
    writeVarint32(bb, 360)
    writeVarint64(bb, $SEGY_BIN_BYTE_OFFSET_FOR_TRACES)
  }

  // optional int32 SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS = 46;
  let $SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS = message.SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS
  if ($SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS !== undefined) {
    writeVarint32(bb, 368)
    writeVarint64(bb, intToLong($SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS))
  }
}

export function decodeBinaryHeader(binary: Uint8Array): BinaryHeader {
  return _decodeBinaryHeader(wrapByteBuffer(binary))
}

function _decodeBinaryHeader(bb: ByteBuffer): BinaryHeader {
  let message: BinaryHeader = {} as any

  end_of_message: while (!isAtEnd(bb)) {
    let tag = readVarint32(bb)

    switch (tag >>> 3) {
      case 0:
        break end_of_message

      // optional int32 JobID = 1;
      case 1: {
        message.JobID = readVarint32(bb)
        break
      }

      // optional int32 LineNumber = 2;
      case 2: {
        message.LineNumber = readVarint32(bb)
        break
      }

      // optional int32 ReelNumber = 3;
      case 3: {
        message.ReelNumber = readVarint32(bb)
        break
      }

      // optional int32 Traces = 4;
      case 4: {
        message.Traces = readVarint32(bb)
        break
      }

      // optional int32 AuxTraces = 5;
      case 5: {
        message.AuxTraces = readVarint32(bb)
        break
      }

      // optional int32 Interval = 6;
      case 6: {
        message.Interval = readVarint32(bb)
        break
      }

      // optional int32 IntervalOriginal = 7;
      case 7: {
        message.IntervalOriginal = readVarint32(bb)
        break
      }

      // optional int32 Samples = 8;
      case 8: {
        message.Samples = readVarint32(bb)
        break
      }

      // optional int32 SamplesOriginal = 9;
      case 9: {
        message.SamplesOriginal = readVarint32(bb)
        break
      }

      // optional int32 Format = 10;
      case 10: {
        message.Format = readVarint32(bb)
        break
      }

      // optional int32 EnsembleFold = 11;
      case 11: {
        message.EnsembleFold = readVarint32(bb)
        break
      }

      // optional int32 SortingCode = 12;
      case 12: {
        message.SortingCode = readVarint32(bb)
        break
      }

      // optional int32 VerticalSum = 13;
      case 13: {
        message.VerticalSum = readVarint32(bb)
        break
      }

      // optional int32 SweepFrequencyStart = 14;
      case 14: {
        message.SweepFrequencyStart = readVarint32(bb)
        break
      }

      // optional int32 SweepFrequencyEnd = 15;
      case 15: {
        message.SweepFrequencyEnd = readVarint32(bb)
        break
      }

      // optional int32 SweepLength = 16;
      case 16: {
        message.SweepLength = readVarint32(bb)
        break
      }

      // optional int32 Sweep = 17;
      case 17: {
        message.Sweep = readVarint32(bb)
        break
      }

      // optional int32 SweepChannel = 18;
      case 18: {
        message.SweepChannel = readVarint32(bb)
        break
      }

      // optional int32 SweepTaperStart = 19;
      case 19: {
        message.SweepTaperStart = readVarint32(bb)
        break
      }

      // optional int32 SweepTaperEnd = 20;
      case 20: {
        message.SweepTaperEnd = readVarint32(bb)
        break
      }

      // optional int32 Taper = 21;
      case 21: {
        message.Taper = readVarint32(bb)
        break
      }

      // optional int32 CorrelatedTraces = 22;
      case 22: {
        message.CorrelatedTraces = readVarint32(bb)
        break
      }

      // optional int32 BinaryGainRecovery = 23;
      case 23: {
        message.BinaryGainRecovery = readVarint32(bb)
        break
      }

      // optional int32 AmplitudeRecovery = 24;
      case 24: {
        message.AmplitudeRecovery = readVarint32(bb)
        break
      }

      // optional int32 MeasurementSystem = 25;
      case 25: {
        message.MeasurementSystem = readVarint32(bb)
        break
      }

      // optional int32 ImpulseSignalPolarity = 26;
      case 26: {
        message.ImpulseSignalPolarity = readVarint32(bb)
        break
      }

      // optional int32 VibratoryPolarity = 27;
      case 27: {
        message.VibratoryPolarity = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_EXT_TRACES = 28;
      case 28: {
        message.SEGY_BIN_EXT_TRACES = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_EXT_AUX_TRACES = 29;
      case 29: {
        message.SEGY_BIN_EXT_AUX_TRACES = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_DT = 30;
      case 30: {
        message.SEGY_BIN_DT = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_EXT_SAMPLES = 31;
      case 31: {
        message.SEGY_BIN_EXT_SAMPLES = readVarint32(bb)
        break
      }

      // optional int64 SEGY_BIN_EXT_SAMPLE_INTERVAL = 32;
      case 32: {
        message.SEGY_BIN_EXT_SAMPLE_INTERVAL = readVarint64(bb, /* unsigned */ false)
        break
      }

      // optional int64 SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG = 33;
      case 33: {
        message.SEGY_BIN_EXT_SAMPLE_INTERVAL_ORIG = readVarint64(bb, /* unsigned */ false)
        break
      }

      // optional int32 SEGY_BIN_EXT_SAMPLES_ORIGINAL = 34;
      case 34: {
        message.SEGY_BIN_EXT_SAMPLES_ORIGINAL = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_EXT_ENSEMBLE_FOLD = 35;
      case 35: {
        message.SEGY_BIN_EXT_ENSEMBLE_FOLD = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_EXT_BYTE_ORDER_CHECK = 36;
      case 36: {
        message.SEGY_BIN_EXT_BYTE_ORDER_CHECK = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_NS = 37;
      case 37: {
        message.SEGY_BIN_NS = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_SEGY_REVISION_MAJOR = 38;
      case 38: {
        message.SEGY_BIN_SEGY_REVISION_MAJOR = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_SEGY_REVISION_MINOR = 39;
      case 39: {
        message.SEGY_BIN_SEGY_REVISION_MINOR = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_FIXED_LENGTH_TRACES = 40;
      case 40: {
        message.SEGY_BIN_FIXED_LENGTH_TRACES = readVarint32(bb)
        break
      }

      // optional int32 SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS = 41;
      case 41: {
        message.SEG_BIN_EXT_NUMBER_OF_EXT_FILE_HEADERS = readVarint32(bb)
        break
      }

      // optional int32 SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS = 42;
      case 42: {
        message.SEG_BIN_EXT_MAX_NUMBER_OF_ADDITIONAL_TRACE_HEADERS = readVarint32(bb)
        break
      }

      // optional int32 SEGY_BIN_TIME_BASIS_CODE = 43;
      case 43: {
        message.SEGY_BIN_TIME_BASIS_CODE = readVarint32(bb)
        break
      }

      // optional uint64 SEGY_BIN_TRACE_NUMBER = 44;
      case 44: {
        message.SEGY_BIN_TRACE_NUMBER = readVarint64(bb, /* unsigned */ true)
        break
      }

      // optional uint64 SEGY_BIN_BYTE_OFFSET_FOR_TRACES = 45;
      case 45: {
        message.SEGY_BIN_BYTE_OFFSET_FOR_TRACES = readVarint64(bb, /* unsigned */ true)
        break
      }

      // optional int32 SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS = 46;
      case 46: {
        message.SEGY_BIN_NUMBER_OF_3200_BYTE_TRAILERS = readVarint32(bb)
        break
      }

      default:
        skipUnknownField(bb, tag & 7)
    }
  }

  return message
}

export interface SliceHeader {
  xline?: number
  traces?: Trace[]
}

export function encodeSliceHeader(message: SliceHeader): Uint8Array {
  let bb = popByteBuffer()
  _encodeSliceHeader(message, bb)
  return toUint8Array(bb)
}

function _encodeSliceHeader(message: SliceHeader, bb: ByteBuffer): void {
  // optional int32 xline = 1;
  let $xline = message.xline
  if ($xline !== undefined) {
    writeVarint32(bb, 8)
    writeVarint64(bb, intToLong($xline))
  }

  // repeated Trace traces = 2;
  let array$traces = message.traces
  if (array$traces !== undefined) {
    for (let value of array$traces) {
      writeVarint32(bb, 18)
      let nested = popByteBuffer()
      _encodeTrace(value, nested)
      writeVarint32(bb, nested.limit)
      writeByteBuffer(bb, nested)
      pushByteBuffer(nested)
    }
  }
}

export function decodeSliceHeader(binary: Uint8Array): SliceHeader {
  return _decodeSliceHeader(wrapByteBuffer(binary))
}

function _decodeSliceHeader(bb: ByteBuffer): SliceHeader {
  let message: SliceHeader = {} as any

  end_of_message: while (!isAtEnd(bb)) {
    let tag = readVarint32(bb)

    switch (tag >>> 3) {
      case 0:
        break end_of_message

      // optional int32 xline = 1;
      case 1: {
        message.xline = readVarint32(bb)
        break
      }

      // repeated Trace traces = 2;
      case 2: {
        let limit = pushTemporaryLength(bb)
        let values = message.traces || (message.traces = [])
        values.push(_decodeTrace(bb))
        bb.limit = limit
        break
      }

      default:
        skipUnknownField(bb, tag & 7)
    }
  }

  return message
}

export interface Trace {
  TRACE_SEQUENCE_LINE?: number
  TRACE_SEQUENCE_FILE?: number
  FieldRecord?: number
  TraceNumber?: number
  EnergySourcePoint?: number
  CDP?: number
  CDP_TRACE?: number
  TraceIdentificationCode?: number
  NSummedTraces?: number
  NStackedTraces?: number
  DataUse?: number
  offset?: number
  ReceiverGroupElevation?: number
  SourceSurfaceElevation?: number
  SourceDepth?: number
  ReceiverDatumElevation?: number
  SourceDatumElevation?: number
  SourceWaterDepth?: number
  GroupWaterDepth?: number
  ElevationScalar?: number
  SourceGroupScalar?: number
  SourceX?: number
  SourceY?: number
  GroupX?: number
  GroupY?: number
  CoordinateUnits?: number
  WeatheringVelocity?: number
  SubWeatheringVelocity?: number
  SourceUpholeTime?: number
  GroupUpholeTime?: number
  SourceStaticCorrection?: number
  GroupStaticCorrection?: number
  TotalStaticApplied?: number
  LagTimeA?: number
  LagTimeB?: number
  DelayRecordingTime?: number
  MuteTimeStart?: number
  MuteTimeEND?: number
  TRACE_SAMPLE_COUNT?: number
  TRACE_SAMPLE_INTERVAL?: number
  GainType?: number
  InstrumentGainConstant?: number
  InstrumentInitialGain?: number
  Correlated?: number
  SweepFrequencyStart?: number
  SweepFrequencyEnd?: number
  SweepLength?: number
  SweepType?: number
  SweepTraceTaperLengthStart?: number
  SweepTraceTaperLengthEnd?: number
  TaperType?: number
  AliasFilterFrequency?: number
  AliasFilterSlope?: number
  NotchFilterFrequency?: number
  NotchFilterSlope?: number
  LowCutFrequency?: number
  HighCutFrequency?: number
  LowCutSlope?: number
  HighCutSlope?: number
  YearDataRecorded?: number
  DayOfYear?: number
  HourOfDay?: number
  MinuteOfHour?: number
  SecondOfMinute?: number
  TimeBaseCode?: number
  TraceWeightingFactor?: number
  GeophoneGroupNumberRoll1?: number
  GeophoneGroupNumberFirstTraceOrigField?: number
  GeophoneGroupNumberLastTraceOrigField?: number
  GapSize?: number
  OverTravel?: number
  CDP_X?: number
  CDP_Y?: number
  INLINE_3D?: number
  CROSSLINE_3D?: number
  ShotPoint?: number
  ShotPointScalar?: number
  TraceValueMeasurementUnit?: number
  TransductionConstantMantissa?: number
  TransductionConstantPower?: number
  TransductionUnit?: number
  TraceIdentifier?: number
  ScalarTraceHeader?: number
  SourceType?: number
  SourceEnergyDirectionMantissa?: number
  SourceEnergyDirectionExponent?: number
  SourceMeasurementMantissa?: number
  SourceMeasurementExponent?: number
  SourceMeasurementUnit?: number
  UnassignedInt1?: number
  UnassignedInt2?: number
}

export function encodeTrace(message: Trace): Uint8Array {
  let bb = popByteBuffer()
  _encodeTrace(message, bb)
  return toUint8Array(bb)
}

function _encodeTrace(message: Trace, bb: ByteBuffer): void {
  // optional int32 TRACE_SEQUENCE_LINE = 1;
  let $TRACE_SEQUENCE_LINE = message.TRACE_SEQUENCE_LINE
  if ($TRACE_SEQUENCE_LINE !== undefined) {
    writeVarint32(bb, 8)
    writeVarint64(bb, intToLong($TRACE_SEQUENCE_LINE))
  }

  // optional int32 TRACE_SEQUENCE_FILE = 2;
  let $TRACE_SEQUENCE_FILE = message.TRACE_SEQUENCE_FILE
  if ($TRACE_SEQUENCE_FILE !== undefined) {
    writeVarint32(bb, 16)
    writeVarint64(bb, intToLong($TRACE_SEQUENCE_FILE))
  }

  // optional int32 FieldRecord = 3;
  let $FieldRecord = message.FieldRecord
  if ($FieldRecord !== undefined) {
    writeVarint32(bb, 24)
    writeVarint64(bb, intToLong($FieldRecord))
  }

  // optional int32 TraceNumber = 4;
  let $TraceNumber = message.TraceNumber
  if ($TraceNumber !== undefined) {
    writeVarint32(bb, 32)
    writeVarint64(bb, intToLong($TraceNumber))
  }

  // optional int32 EnergySourcePoint = 5;
  let $EnergySourcePoint = message.EnergySourcePoint
  if ($EnergySourcePoint !== undefined) {
    writeVarint32(bb, 40)
    writeVarint64(bb, intToLong($EnergySourcePoint))
  }

  // optional int32 CDP = 6;
  let $CDP = message.CDP
  if ($CDP !== undefined) {
    writeVarint32(bb, 48)
    writeVarint64(bb, intToLong($CDP))
  }

  // optional int32 CDP_TRACE = 7;
  let $CDP_TRACE = message.CDP_TRACE
  if ($CDP_TRACE !== undefined) {
    writeVarint32(bb, 56)
    writeVarint64(bb, intToLong($CDP_TRACE))
  }

  // optional int32 TraceIdentificationCode = 8;
  let $TraceIdentificationCode = message.TraceIdentificationCode
  if ($TraceIdentificationCode !== undefined) {
    writeVarint32(bb, 64)
    writeVarint64(bb, intToLong($TraceIdentificationCode))
  }

  // optional int32 NSummedTraces = 9;
  let $NSummedTraces = message.NSummedTraces
  if ($NSummedTraces !== undefined) {
    writeVarint32(bb, 72)
    writeVarint64(bb, intToLong($NSummedTraces))
  }

  // optional int32 NStackedTraces = 10;
  let $NStackedTraces = message.NStackedTraces
  if ($NStackedTraces !== undefined) {
    writeVarint32(bb, 80)
    writeVarint64(bb, intToLong($NStackedTraces))
  }

  // optional int32 DataUse = 11;
  let $DataUse = message.DataUse
  if ($DataUse !== undefined) {
    writeVarint32(bb, 88)
    writeVarint64(bb, intToLong($DataUse))
  }

  // optional int32 offset = 12;
  let $offset = message.offset
  if ($offset !== undefined) {
    writeVarint32(bb, 96)
    writeVarint64(bb, intToLong($offset))
  }

  // optional int32 ReceiverGroupElevation = 13;
  let $ReceiverGroupElevation = message.ReceiverGroupElevation
  if ($ReceiverGroupElevation !== undefined) {
    writeVarint32(bb, 104)
    writeVarint64(bb, intToLong($ReceiverGroupElevation))
  }

  // optional int32 SourceSurfaceElevation = 14;
  let $SourceSurfaceElevation = message.SourceSurfaceElevation
  if ($SourceSurfaceElevation !== undefined) {
    writeVarint32(bb, 112)
    writeVarint64(bb, intToLong($SourceSurfaceElevation))
  }

  // optional int32 SourceDepth = 15;
  let $SourceDepth = message.SourceDepth
  if ($SourceDepth !== undefined) {
    writeVarint32(bb, 120)
    writeVarint64(bb, intToLong($SourceDepth))
  }

  // optional int32 ReceiverDatumElevation = 16;
  let $ReceiverDatumElevation = message.ReceiverDatumElevation
  if ($ReceiverDatumElevation !== undefined) {
    writeVarint32(bb, 128)
    writeVarint64(bb, intToLong($ReceiverDatumElevation))
  }

  // optional int32 SourceDatumElevation = 17;
  let $SourceDatumElevation = message.SourceDatumElevation
  if ($SourceDatumElevation !== undefined) {
    writeVarint32(bb, 136)
    writeVarint64(bb, intToLong($SourceDatumElevation))
  }

  // optional int32 SourceWaterDepth = 18;
  let $SourceWaterDepth = message.SourceWaterDepth
  if ($SourceWaterDepth !== undefined) {
    writeVarint32(bb, 144)
    writeVarint64(bb, intToLong($SourceWaterDepth))
  }

  // optional int32 GroupWaterDepth = 19;
  let $GroupWaterDepth = message.GroupWaterDepth
  if ($GroupWaterDepth !== undefined) {
    writeVarint32(bb, 152)
    writeVarint64(bb, intToLong($GroupWaterDepth))
  }

  // optional int32 ElevationScalar = 20;
  let $ElevationScalar = message.ElevationScalar
  if ($ElevationScalar !== undefined) {
    writeVarint32(bb, 160)
    writeVarint64(bb, intToLong($ElevationScalar))
  }

  // optional int32 SourceGroupScalar = 21;
  let $SourceGroupScalar = message.SourceGroupScalar
  if ($SourceGroupScalar !== undefined) {
    writeVarint32(bb, 168)
    writeVarint64(bb, intToLong($SourceGroupScalar))
  }

  // optional int32 SourceX = 22;
  let $SourceX = message.SourceX
  if ($SourceX !== undefined) {
    writeVarint32(bb, 176)
    writeVarint64(bb, intToLong($SourceX))
  }

  // optional int32 SourceY = 23;
  let $SourceY = message.SourceY
  if ($SourceY !== undefined) {
    writeVarint32(bb, 184)
    writeVarint64(bb, intToLong($SourceY))
  }

  // optional int32 GroupX = 24;
  let $GroupX = message.GroupX
  if ($GroupX !== undefined) {
    writeVarint32(bb, 192)
    writeVarint64(bb, intToLong($GroupX))
  }

  // optional int32 GroupY = 25;
  let $GroupY = message.GroupY
  if ($GroupY !== undefined) {
    writeVarint32(bb, 200)
    writeVarint64(bb, intToLong($GroupY))
  }

  // optional int32 CoordinateUnits = 26;
  let $CoordinateUnits = message.CoordinateUnits
  if ($CoordinateUnits !== undefined) {
    writeVarint32(bb, 208)
    writeVarint64(bb, intToLong($CoordinateUnits))
  }

  // optional int32 WeatheringVelocity = 27;
  let $WeatheringVelocity = message.WeatheringVelocity
  if ($WeatheringVelocity !== undefined) {
    writeVarint32(bb, 216)
    writeVarint64(bb, intToLong($WeatheringVelocity))
  }

  // optional int32 SubWeatheringVelocity = 28;
  let $SubWeatheringVelocity = message.SubWeatheringVelocity
  if ($SubWeatheringVelocity !== undefined) {
    writeVarint32(bb, 224)
    writeVarint64(bb, intToLong($SubWeatheringVelocity))
  }

  // optional int32 SourceUpholeTime = 29;
  let $SourceUpholeTime = message.SourceUpholeTime
  if ($SourceUpholeTime !== undefined) {
    writeVarint32(bb, 232)
    writeVarint64(bb, intToLong($SourceUpholeTime))
  }

  // optional int32 GroupUpholeTime = 30;
  let $GroupUpholeTime = message.GroupUpholeTime
  if ($GroupUpholeTime !== undefined) {
    writeVarint32(bb, 240)
    writeVarint64(bb, intToLong($GroupUpholeTime))
  }

  // optional int32 SourceStaticCorrection = 31;
  let $SourceStaticCorrection = message.SourceStaticCorrection
  if ($SourceStaticCorrection !== undefined) {
    writeVarint32(bb, 248)
    writeVarint64(bb, intToLong($SourceStaticCorrection))
  }

  // optional int32 GroupStaticCorrection = 32;
  let $GroupStaticCorrection = message.GroupStaticCorrection
  if ($GroupStaticCorrection !== undefined) {
    writeVarint32(bb, 256)
    writeVarint64(bb, intToLong($GroupStaticCorrection))
  }

  // optional int32 TotalStaticApplied = 33;
  let $TotalStaticApplied = message.TotalStaticApplied
  if ($TotalStaticApplied !== undefined) {
    writeVarint32(bb, 264)
    writeVarint64(bb, intToLong($TotalStaticApplied))
  }

  // optional int32 LagTimeA = 34;
  let $LagTimeA = message.LagTimeA
  if ($LagTimeA !== undefined) {
    writeVarint32(bb, 272)
    writeVarint64(bb, intToLong($LagTimeA))
  }

  // optional int32 LagTimeB = 35;
  let $LagTimeB = message.LagTimeB
  if ($LagTimeB !== undefined) {
    writeVarint32(bb, 280)
    writeVarint64(bb, intToLong($LagTimeB))
  }

  // optional int32 DelayRecordingTime = 36;
  let $DelayRecordingTime = message.DelayRecordingTime
  if ($DelayRecordingTime !== undefined) {
    writeVarint32(bb, 288)
    writeVarint64(bb, intToLong($DelayRecordingTime))
  }

  // optional int32 MuteTimeStart = 37;
  let $MuteTimeStart = message.MuteTimeStart
  if ($MuteTimeStart !== undefined) {
    writeVarint32(bb, 296)
    writeVarint64(bb, intToLong($MuteTimeStart))
  }

  // optional int32 MuteTimeEND = 38;
  let $MuteTimeEND = message.MuteTimeEND
  if ($MuteTimeEND !== undefined) {
    writeVarint32(bb, 304)
    writeVarint64(bb, intToLong($MuteTimeEND))
  }

  // optional int32 TRACE_SAMPLE_COUNT = 39;
  let $TRACE_SAMPLE_COUNT = message.TRACE_SAMPLE_COUNT
  if ($TRACE_SAMPLE_COUNT !== undefined) {
    writeVarint32(bb, 312)
    writeVarint64(bb, intToLong($TRACE_SAMPLE_COUNT))
  }

  // optional int32 TRACE_SAMPLE_INTERVAL = 40;
  let $TRACE_SAMPLE_INTERVAL = message.TRACE_SAMPLE_INTERVAL
  if ($TRACE_SAMPLE_INTERVAL !== undefined) {
    writeVarint32(bb, 320)
    writeVarint64(bb, intToLong($TRACE_SAMPLE_INTERVAL))
  }

  // optional int32 GainType = 41;
  let $GainType = message.GainType
  if ($GainType !== undefined) {
    writeVarint32(bb, 328)
    writeVarint64(bb, intToLong($GainType))
  }

  // optional int32 InstrumentGainConstant = 42;
  let $InstrumentGainConstant = message.InstrumentGainConstant
  if ($InstrumentGainConstant !== undefined) {
    writeVarint32(bb, 336)
    writeVarint64(bb, intToLong($InstrumentGainConstant))
  }

  // optional int32 InstrumentInitialGain = 43;
  let $InstrumentInitialGain = message.InstrumentInitialGain
  if ($InstrumentInitialGain !== undefined) {
    writeVarint32(bb, 344)
    writeVarint64(bb, intToLong($InstrumentInitialGain))
  }

  // optional int32 Correlated = 44;
  let $Correlated = message.Correlated
  if ($Correlated !== undefined) {
    writeVarint32(bb, 352)
    writeVarint64(bb, intToLong($Correlated))
  }

  // optional int32 SweepFrequencyStart = 45;
  let $SweepFrequencyStart = message.SweepFrequencyStart
  if ($SweepFrequencyStart !== undefined) {
    writeVarint32(bb, 360)
    writeVarint64(bb, intToLong($SweepFrequencyStart))
  }

  // optional int32 SweepFrequencyEnd = 46;
  let $SweepFrequencyEnd = message.SweepFrequencyEnd
  if ($SweepFrequencyEnd !== undefined) {
    writeVarint32(bb, 368)
    writeVarint64(bb, intToLong($SweepFrequencyEnd))
  }

  // optional int32 SweepLength = 47;
  let $SweepLength = message.SweepLength
  if ($SweepLength !== undefined) {
    writeVarint32(bb, 376)
    writeVarint64(bb, intToLong($SweepLength))
  }

  // optional int32 SweepType = 48;
  let $SweepType = message.SweepType
  if ($SweepType !== undefined) {
    writeVarint32(bb, 384)
    writeVarint64(bb, intToLong($SweepType))
  }

  // optional int32 SweepTraceTaperLengthStart = 49;
  let $SweepTraceTaperLengthStart = message.SweepTraceTaperLengthStart
  if ($SweepTraceTaperLengthStart !== undefined) {
    writeVarint32(bb, 392)
    writeVarint64(bb, intToLong($SweepTraceTaperLengthStart))
  }

  // optional int32 SweepTraceTaperLengthEnd = 50;
  let $SweepTraceTaperLengthEnd = message.SweepTraceTaperLengthEnd
  if ($SweepTraceTaperLengthEnd !== undefined) {
    writeVarint32(bb, 400)
    writeVarint64(bb, intToLong($SweepTraceTaperLengthEnd))
  }

  // optional int32 TaperType = 51;
  let $TaperType = message.TaperType
  if ($TaperType !== undefined) {
    writeVarint32(bb, 408)
    writeVarint64(bb, intToLong($TaperType))
  }

  // optional int32 AliasFilterFrequency = 52;
  let $AliasFilterFrequency = message.AliasFilterFrequency
  if ($AliasFilterFrequency !== undefined) {
    writeVarint32(bb, 416)
    writeVarint64(bb, intToLong($AliasFilterFrequency))
  }

  // optional int32 AliasFilterSlope = 53;
  let $AliasFilterSlope = message.AliasFilterSlope
  if ($AliasFilterSlope !== undefined) {
    writeVarint32(bb, 424)
    writeVarint64(bb, intToLong($AliasFilterSlope))
  }

  // optional int32 NotchFilterFrequency = 54;
  let $NotchFilterFrequency = message.NotchFilterFrequency
  if ($NotchFilterFrequency !== undefined) {
    writeVarint32(bb, 432)
    writeVarint64(bb, intToLong($NotchFilterFrequency))
  }

  // optional int32 NotchFilterSlope = 55;
  let $NotchFilterSlope = message.NotchFilterSlope
  if ($NotchFilterSlope !== undefined) {
    writeVarint32(bb, 440)
    writeVarint64(bb, intToLong($NotchFilterSlope))
  }

  // optional int32 LowCutFrequency = 56;
  let $LowCutFrequency = message.LowCutFrequency
  if ($LowCutFrequency !== undefined) {
    writeVarint32(bb, 448)
    writeVarint64(bb, intToLong($LowCutFrequency))
  }

  // optional int32 HighCutFrequency = 57;
  let $HighCutFrequency = message.HighCutFrequency
  if ($HighCutFrequency !== undefined) {
    writeVarint32(bb, 456)
    writeVarint64(bb, intToLong($HighCutFrequency))
  }

  // optional int32 LowCutSlope = 58;
  let $LowCutSlope = message.LowCutSlope
  if ($LowCutSlope !== undefined) {
    writeVarint32(bb, 464)
    writeVarint64(bb, intToLong($LowCutSlope))
  }

  // optional int32 HighCutSlope = 59;
  let $HighCutSlope = message.HighCutSlope
  if ($HighCutSlope !== undefined) {
    writeVarint32(bb, 472)
    writeVarint64(bb, intToLong($HighCutSlope))
  }

  // optional int32 YearDataRecorded = 60;
  let $YearDataRecorded = message.YearDataRecorded
  if ($YearDataRecorded !== undefined) {
    writeVarint32(bb, 480)
    writeVarint64(bb, intToLong($YearDataRecorded))
  }

  // optional int32 DayOfYear = 61;
  let $DayOfYear = message.DayOfYear
  if ($DayOfYear !== undefined) {
    writeVarint32(bb, 488)
    writeVarint64(bb, intToLong($DayOfYear))
  }

  // optional int32 HourOfDay = 62;
  let $HourOfDay = message.HourOfDay
  if ($HourOfDay !== undefined) {
    writeVarint32(bb, 496)
    writeVarint64(bb, intToLong($HourOfDay))
  }

  // optional int32 MinuteOfHour = 63;
  let $MinuteOfHour = message.MinuteOfHour
  if ($MinuteOfHour !== undefined) {
    writeVarint32(bb, 504)
    writeVarint64(bb, intToLong($MinuteOfHour))
  }

  // optional int32 SecondOfMinute = 64;
  let $SecondOfMinute = message.SecondOfMinute
  if ($SecondOfMinute !== undefined) {
    writeVarint32(bb, 512)
    writeVarint64(bb, intToLong($SecondOfMinute))
  }

  // optional int32 TimeBaseCode = 65;
  let $TimeBaseCode = message.TimeBaseCode
  if ($TimeBaseCode !== undefined) {
    writeVarint32(bb, 520)
    writeVarint64(bb, intToLong($TimeBaseCode))
  }

  // optional int32 TraceWeightingFactor = 66;
  let $TraceWeightingFactor = message.TraceWeightingFactor
  if ($TraceWeightingFactor !== undefined) {
    writeVarint32(bb, 528)
    writeVarint64(bb, intToLong($TraceWeightingFactor))
  }

  // optional int32 GeophoneGroupNumberRoll1 = 67;
  let $GeophoneGroupNumberRoll1 = message.GeophoneGroupNumberRoll1
  if ($GeophoneGroupNumberRoll1 !== undefined) {
    writeVarint32(bb, 536)
    writeVarint64(bb, intToLong($GeophoneGroupNumberRoll1))
  }

  // optional int32 GeophoneGroupNumberFirstTraceOrigField = 68;
  let $GeophoneGroupNumberFirstTraceOrigField = message.GeophoneGroupNumberFirstTraceOrigField
  if ($GeophoneGroupNumberFirstTraceOrigField !== undefined) {
    writeVarint32(bb, 544)
    writeVarint64(bb, intToLong($GeophoneGroupNumberFirstTraceOrigField))
  }

  // optional int32 GeophoneGroupNumberLastTraceOrigField = 69;
  let $GeophoneGroupNumberLastTraceOrigField = message.GeophoneGroupNumberLastTraceOrigField
  if ($GeophoneGroupNumberLastTraceOrigField !== undefined) {
    writeVarint32(bb, 552)
    writeVarint64(bb, intToLong($GeophoneGroupNumberLastTraceOrigField))
  }

  // optional int32 GapSize = 70;
  let $GapSize = message.GapSize
  if ($GapSize !== undefined) {
    writeVarint32(bb, 560)
    writeVarint64(bb, intToLong($GapSize))
  }

  // optional int32 OverTravel = 71;
  let $OverTravel = message.OverTravel
  if ($OverTravel !== undefined) {
    writeVarint32(bb, 568)
    writeVarint64(bb, intToLong($OverTravel))
  }

  // optional int32 CDP_X = 72;
  let $CDP_X = message.CDP_X
  if ($CDP_X !== undefined) {
    writeVarint32(bb, 576)
    writeVarint64(bb, intToLong($CDP_X))
  }

  // optional int32 CDP_Y = 73;
  let $CDP_Y = message.CDP_Y
  if ($CDP_Y !== undefined) {
    writeVarint32(bb, 584)
    writeVarint64(bb, intToLong($CDP_Y))
  }

  // optional int32 INLINE_3D = 74;
  let $INLINE_3D = message.INLINE_3D
  if ($INLINE_3D !== undefined) {
    writeVarint32(bb, 592)
    writeVarint64(bb, intToLong($INLINE_3D))
  }

  // optional int32 CROSSLINE_3D = 75;
  let $CROSSLINE_3D = message.CROSSLINE_3D
  if ($CROSSLINE_3D !== undefined) {
    writeVarint32(bb, 600)
    writeVarint64(bb, intToLong($CROSSLINE_3D))
  }

  // optional int32 ShotPoint = 76;
  let $ShotPoint = message.ShotPoint
  if ($ShotPoint !== undefined) {
    writeVarint32(bb, 608)
    writeVarint64(bb, intToLong($ShotPoint))
  }

  // optional int32 ShotPointScalar = 77;
  let $ShotPointScalar = message.ShotPointScalar
  if ($ShotPointScalar !== undefined) {
    writeVarint32(bb, 616)
    writeVarint64(bb, intToLong($ShotPointScalar))
  }

  // optional int32 TraceValueMeasurementUnit = 78;
  let $TraceValueMeasurementUnit = message.TraceValueMeasurementUnit
  if ($TraceValueMeasurementUnit !== undefined) {
    writeVarint32(bb, 624)
    writeVarint64(bb, intToLong($TraceValueMeasurementUnit))
  }

  // optional int32 TransductionConstantMantissa = 79;
  let $TransductionConstantMantissa = message.TransductionConstantMantissa
  if ($TransductionConstantMantissa !== undefined) {
    writeVarint32(bb, 632)
    writeVarint64(bb, intToLong($TransductionConstantMantissa))
  }

  // optional int32 TransductionConstantPower = 80;
  let $TransductionConstantPower = message.TransductionConstantPower
  if ($TransductionConstantPower !== undefined) {
    writeVarint32(bb, 640)
    writeVarint64(bb, intToLong($TransductionConstantPower))
  }

  // optional int32 TransductionUnit = 81;
  let $TransductionUnit = message.TransductionUnit
  if ($TransductionUnit !== undefined) {
    writeVarint32(bb, 648)
    writeVarint64(bb, intToLong($TransductionUnit))
  }

  // optional int32 TraceIdentifier = 82;
  let $TraceIdentifier = message.TraceIdentifier
  if ($TraceIdentifier !== undefined) {
    writeVarint32(bb, 656)
    writeVarint64(bb, intToLong($TraceIdentifier))
  }

  // optional int32 ScalarTraceHeader = 83;
  let $ScalarTraceHeader = message.ScalarTraceHeader
  if ($ScalarTraceHeader !== undefined) {
    writeVarint32(bb, 664)
    writeVarint64(bb, intToLong($ScalarTraceHeader))
  }

  // optional int32 SourceType = 84;
  let $SourceType = message.SourceType
  if ($SourceType !== undefined) {
    writeVarint32(bb, 672)
    writeVarint64(bb, intToLong($SourceType))
  }

  // optional int32 SourceEnergyDirectionMantissa = 85;
  let $SourceEnergyDirectionMantissa = message.SourceEnergyDirectionMantissa
  if ($SourceEnergyDirectionMantissa !== undefined) {
    writeVarint32(bb, 680)
    writeVarint64(bb, intToLong($SourceEnergyDirectionMantissa))
  }

  // optional int32 SourceEnergyDirectionExponent = 86;
  let $SourceEnergyDirectionExponent = message.SourceEnergyDirectionExponent
  if ($SourceEnergyDirectionExponent !== undefined) {
    writeVarint32(bb, 688)
    writeVarint64(bb, intToLong($SourceEnergyDirectionExponent))
  }

  // optional int32 SourceMeasurementMantissa = 87;
  let $SourceMeasurementMantissa = message.SourceMeasurementMantissa
  if ($SourceMeasurementMantissa !== undefined) {
    writeVarint32(bb, 696)
    writeVarint64(bb, intToLong($SourceMeasurementMantissa))
  }

  // optional int32 SourceMeasurementExponent = 88;
  let $SourceMeasurementExponent = message.SourceMeasurementExponent
  if ($SourceMeasurementExponent !== undefined) {
    writeVarint32(bb, 704)
    writeVarint64(bb, intToLong($SourceMeasurementExponent))
  }

  // optional int32 SourceMeasurementUnit = 89;
  let $SourceMeasurementUnit = message.SourceMeasurementUnit
  if ($SourceMeasurementUnit !== undefined) {
    writeVarint32(bb, 712)
    writeVarint64(bb, intToLong($SourceMeasurementUnit))
  }

  // optional int32 UnassignedInt1 = 90;
  let $UnassignedInt1 = message.UnassignedInt1
  if ($UnassignedInt1 !== undefined) {
    writeVarint32(bb, 720)
    writeVarint64(bb, intToLong($UnassignedInt1))
  }

  // optional int32 UnassignedInt2 = 91;
  let $UnassignedInt2 = message.UnassignedInt2
  if ($UnassignedInt2 !== undefined) {
    writeVarint32(bb, 728)
    writeVarint64(bb, intToLong($UnassignedInt2))
  }
}

export function decodeTrace(binary: Uint8Array): Trace {
  return _decodeTrace(wrapByteBuffer(binary))
}

function _decodeTrace(bb: ByteBuffer): Trace {
  let message: Trace = {} as any

  end_of_message: while (!isAtEnd(bb)) {
    let tag = readVarint32(bb)

    switch (tag >>> 3) {
      case 0:
        break end_of_message

      // optional int32 TRACE_SEQUENCE_LINE = 1;
      case 1: {
        message.TRACE_SEQUENCE_LINE = readVarint32(bb)
        break
      }

      // optional int32 TRACE_SEQUENCE_FILE = 2;
      case 2: {
        message.TRACE_SEQUENCE_FILE = readVarint32(bb)
        break
      }

      // optional int32 FieldRecord = 3;
      case 3: {
        message.FieldRecord = readVarint32(bb)
        break
      }

      // optional int32 TraceNumber = 4;
      case 4: {
        message.TraceNumber = readVarint32(bb)
        break
      }

      // optional int32 EnergySourcePoint = 5;
      case 5: {
        message.EnergySourcePoint = readVarint32(bb)
        break
      }

      // optional int32 CDP = 6;
      case 6: {
        message.CDP = readVarint32(bb)
        break
      }

      // optional int32 CDP_TRACE = 7;
      case 7: {
        message.CDP_TRACE = readVarint32(bb)
        break
      }

      // optional int32 TraceIdentificationCode = 8;
      case 8: {
        message.TraceIdentificationCode = readVarint32(bb)
        break
      }

      // optional int32 NSummedTraces = 9;
      case 9: {
        message.NSummedTraces = readVarint32(bb)
        break
      }

      // optional int32 NStackedTraces = 10;
      case 10: {
        message.NStackedTraces = readVarint32(bb)
        break
      }

      // optional int32 DataUse = 11;
      case 11: {
        message.DataUse = readVarint32(bb)
        break
      }

      // optional int32 offset = 12;
      case 12: {
        message.offset = readVarint32(bb)
        break
      }

      // optional int32 ReceiverGroupElevation = 13;
      case 13: {
        message.ReceiverGroupElevation = readVarint32(bb)
        break
      }

      // optional int32 SourceSurfaceElevation = 14;
      case 14: {
        message.SourceSurfaceElevation = readVarint32(bb)
        break
      }

      // optional int32 SourceDepth = 15;
      case 15: {
        message.SourceDepth = readVarint32(bb)
        break
      }

      // optional int32 ReceiverDatumElevation = 16;
      case 16: {
        message.ReceiverDatumElevation = readVarint32(bb)
        break
      }

      // optional int32 SourceDatumElevation = 17;
      case 17: {
        message.SourceDatumElevation = readVarint32(bb)
        break
      }

      // optional int32 SourceWaterDepth = 18;
      case 18: {
        message.SourceWaterDepth = readVarint32(bb)
        break
      }

      // optional int32 GroupWaterDepth = 19;
      case 19: {
        message.GroupWaterDepth = readVarint32(bb)
        break
      }

      // optional int32 ElevationScalar = 20;
      case 20: {
        message.ElevationScalar = readVarint32(bb)
        break
      }

      // optional int32 SourceGroupScalar = 21;
      case 21: {
        message.SourceGroupScalar = readVarint32(bb)
        break
      }

      // optional int32 SourceX = 22;
      case 22: {
        message.SourceX = readVarint32(bb)
        break
      }

      // optional int32 SourceY = 23;
      case 23: {
        message.SourceY = readVarint32(bb)
        break
      }

      // optional int32 GroupX = 24;
      case 24: {
        message.GroupX = readVarint32(bb)
        break
      }

      // optional int32 GroupY = 25;
      case 25: {
        message.GroupY = readVarint32(bb)
        break
      }

      // optional int32 CoordinateUnits = 26;
      case 26: {
        message.CoordinateUnits = readVarint32(bb)
        break
      }

      // optional int32 WeatheringVelocity = 27;
      case 27: {
        message.WeatheringVelocity = readVarint32(bb)
        break
      }

      // optional int32 SubWeatheringVelocity = 28;
      case 28: {
        message.SubWeatheringVelocity = readVarint32(bb)
        break
      }

      // optional int32 SourceUpholeTime = 29;
      case 29: {
        message.SourceUpholeTime = readVarint32(bb)
        break
      }

      // optional int32 GroupUpholeTime = 30;
      case 30: {
        message.GroupUpholeTime = readVarint32(bb)
        break
      }

      // optional int32 SourceStaticCorrection = 31;
      case 31: {
        message.SourceStaticCorrection = readVarint32(bb)
        break
      }

      // optional int32 GroupStaticCorrection = 32;
      case 32: {
        message.GroupStaticCorrection = readVarint32(bb)
        break
      }

      // optional int32 TotalStaticApplied = 33;
      case 33: {
        message.TotalStaticApplied = readVarint32(bb)
        break
      }

      // optional int32 LagTimeA = 34;
      case 34: {
        message.LagTimeA = readVarint32(bb)
        break
      }

      // optional int32 LagTimeB = 35;
      case 35: {
        message.LagTimeB = readVarint32(bb)
        break
      }

      // optional int32 DelayRecordingTime = 36;
      case 36: {
        message.DelayRecordingTime = readVarint32(bb)
        break
      }

      // optional int32 MuteTimeStart = 37;
      case 37: {
        message.MuteTimeStart = readVarint32(bb)
        break
      }

      // optional int32 MuteTimeEND = 38;
      case 38: {
        message.MuteTimeEND = readVarint32(bb)
        break
      }

      // optional int32 TRACE_SAMPLE_COUNT = 39;
      case 39: {
        message.TRACE_SAMPLE_COUNT = readVarint32(bb)
        break
      }

      // optional int32 TRACE_SAMPLE_INTERVAL = 40;
      case 40: {
        message.TRACE_SAMPLE_INTERVAL = readVarint32(bb)
        break
      }

      // optional int32 GainType = 41;
      case 41: {
        message.GainType = readVarint32(bb)
        break
      }

      // optional int32 InstrumentGainConstant = 42;
      case 42: {
        message.InstrumentGainConstant = readVarint32(bb)
        break
      }

      // optional int32 InstrumentInitialGain = 43;
      case 43: {
        message.InstrumentInitialGain = readVarint32(bb)
        break
      }

      // optional int32 Correlated = 44;
      case 44: {
        message.Correlated = readVarint32(bb)
        break
      }

      // optional int32 SweepFrequencyStart = 45;
      case 45: {
        message.SweepFrequencyStart = readVarint32(bb)
        break
      }

      // optional int32 SweepFrequencyEnd = 46;
      case 46: {
        message.SweepFrequencyEnd = readVarint32(bb)
        break
      }

      // optional int32 SweepLength = 47;
      case 47: {
        message.SweepLength = readVarint32(bb)
        break
      }

      // optional int32 SweepType = 48;
      case 48: {
        message.SweepType = readVarint32(bb)
        break
      }

      // optional int32 SweepTraceTaperLengthStart = 49;
      case 49: {
        message.SweepTraceTaperLengthStart = readVarint32(bb)
        break
      }

      // optional int32 SweepTraceTaperLengthEnd = 50;
      case 50: {
        message.SweepTraceTaperLengthEnd = readVarint32(bb)
        break
      }

      // optional int32 TaperType = 51;
      case 51: {
        message.TaperType = readVarint32(bb)
        break
      }

      // optional int32 AliasFilterFrequency = 52;
      case 52: {
        message.AliasFilterFrequency = readVarint32(bb)
        break
      }

      // optional int32 AliasFilterSlope = 53;
      case 53: {
        message.AliasFilterSlope = readVarint32(bb)
        break
      }

      // optional int32 NotchFilterFrequency = 54;
      case 54: {
        message.NotchFilterFrequency = readVarint32(bb)
        break
      }

      // optional int32 NotchFilterSlope = 55;
      case 55: {
        message.NotchFilterSlope = readVarint32(bb)
        break
      }

      // optional int32 LowCutFrequency = 56;
      case 56: {
        message.LowCutFrequency = readVarint32(bb)
        break
      }

      // optional int32 HighCutFrequency = 57;
      case 57: {
        message.HighCutFrequency = readVarint32(bb)
        break
      }

      // optional int32 LowCutSlope = 58;
      case 58: {
        message.LowCutSlope = readVarint32(bb)
        break
      }

      // optional int32 HighCutSlope = 59;
      case 59: {
        message.HighCutSlope = readVarint32(bb)
        break
      }

      // optional int32 YearDataRecorded = 60;
      case 60: {
        message.YearDataRecorded = readVarint32(bb)
        break
      }

      // optional int32 DayOfYear = 61;
      case 61: {
        message.DayOfYear = readVarint32(bb)
        break
      }

      // optional int32 HourOfDay = 62;
      case 62: {
        message.HourOfDay = readVarint32(bb)
        break
      }

      // optional int32 MinuteOfHour = 63;
      case 63: {
        message.MinuteOfHour = readVarint32(bb)
        break
      }

      // optional int32 SecondOfMinute = 64;
      case 64: {
        message.SecondOfMinute = readVarint32(bb)
        break
      }

      // optional int32 TimeBaseCode = 65;
      case 65: {
        message.TimeBaseCode = readVarint32(bb)
        break
      }

      // optional int32 TraceWeightingFactor = 66;
      case 66: {
        message.TraceWeightingFactor = readVarint32(bb)
        break
      }

      // optional int32 GeophoneGroupNumberRoll1 = 67;
      case 67: {
        message.GeophoneGroupNumberRoll1 = readVarint32(bb)
        break
      }

      // optional int32 GeophoneGroupNumberFirstTraceOrigField = 68;
      case 68: {
        message.GeophoneGroupNumberFirstTraceOrigField = readVarint32(bb)
        break
      }

      // optional int32 GeophoneGroupNumberLastTraceOrigField = 69;
      case 69: {
        message.GeophoneGroupNumberLastTraceOrigField = readVarint32(bb)
        break
      }

      // optional int32 GapSize = 70;
      case 70: {
        message.GapSize = readVarint32(bb)
        break
      }

      // optional int32 OverTravel = 71;
      case 71: {
        message.OverTravel = readVarint32(bb)
        break
      }

      // optional int32 CDP_X = 72;
      case 72: {
        message.CDP_X = readVarint32(bb)
        break
      }

      // optional int32 CDP_Y = 73;
      case 73: {
        message.CDP_Y = readVarint32(bb)
        break
      }

      // optional int32 INLINE_3D = 74;
      case 74: {
        message.INLINE_3D = readVarint32(bb)
        break
      }

      // optional int32 CROSSLINE_3D = 75;
      case 75: {
        message.CROSSLINE_3D = readVarint32(bb)
        break
      }

      // optional int32 ShotPoint = 76;
      case 76: {
        message.ShotPoint = readVarint32(bb)
        break
      }

      // optional int32 ShotPointScalar = 77;
      case 77: {
        message.ShotPointScalar = readVarint32(bb)
        break
      }

      // optional int32 TraceValueMeasurementUnit = 78;
      case 78: {
        message.TraceValueMeasurementUnit = readVarint32(bb)
        break
      }

      // optional int32 TransductionConstantMantissa = 79;
      case 79: {
        message.TransductionConstantMantissa = readVarint32(bb)
        break
      }

      // optional int32 TransductionConstantPower = 80;
      case 80: {
        message.TransductionConstantPower = readVarint32(bb)
        break
      }

      // optional int32 TransductionUnit = 81;
      case 81: {
        message.TransductionUnit = readVarint32(bb)
        break
      }

      // optional int32 TraceIdentifier = 82;
      case 82: {
        message.TraceIdentifier = readVarint32(bb)
        break
      }

      // optional int32 ScalarTraceHeader = 83;
      case 83: {
        message.ScalarTraceHeader = readVarint32(bb)
        break
      }

      // optional int32 SourceType = 84;
      case 84: {
        message.SourceType = readVarint32(bb)
        break
      }

      // optional int32 SourceEnergyDirectionMantissa = 85;
      case 85: {
        message.SourceEnergyDirectionMantissa = readVarint32(bb)
        break
      }

      // optional int32 SourceEnergyDirectionExponent = 86;
      case 86: {
        message.SourceEnergyDirectionExponent = readVarint32(bb)
        break
      }

      // optional int32 SourceMeasurementMantissa = 87;
      case 87: {
        message.SourceMeasurementMantissa = readVarint32(bb)
        break
      }

      // optional int32 SourceMeasurementExponent = 88;
      case 88: {
        message.SourceMeasurementExponent = readVarint32(bb)
        break
      }

      // optional int32 SourceMeasurementUnit = 89;
      case 89: {
        message.SourceMeasurementUnit = readVarint32(bb)
        break
      }

      // optional int32 UnassignedInt1 = 90;
      case 90: {
        message.UnassignedInt1 = readVarint32(bb)
        break
      }

      // optional int32 UnassignedInt2 = 91;
      case 91: {
        message.UnassignedInt2 = readVarint32(bb)
        break
      }

      default:
        skipUnknownField(bb, tag & 7)
    }
  }

  return message
}

export interface Long {
  low: number
  high: number
  unsigned: boolean
}

interface ByteBuffer {
  bytes: Uint8Array
  offset: number
  limit: number
}

function pushTemporaryLength(bb: ByteBuffer): number {
  let length = readVarint32(bb)
  let limit = bb.limit
  bb.limit = bb.offset + length
  return limit
}

function skipUnknownField(bb: ByteBuffer, type: number): void {
  switch (type) {
    case 0:
      while (readByte(bb) & 0x80) {}
      break
    case 2:
      skip(bb, readVarint32(bb))
      break
    case 5:
      skip(bb, 4)
      break
    case 1:
      skip(bb, 8)
      break
    default:
      throw new Error('Unimplemented type: ' + type)
  }
}

function stringToLong(value: string): Long {
  return {
    low: value.charCodeAt(0) | (value.charCodeAt(1) << 16),
    high: value.charCodeAt(2) | (value.charCodeAt(3) << 16),
    unsigned: false,
  }
}

function longToString(value: Long): string {
  let low = value.low
  let high = value.high
  return String.fromCharCode(low & 0xffff, low >>> 16, high & 0xffff, high >>> 16)
}

// The code below was modified from https://github.com/protobufjs/bytebuffer.js
// which is under the Apache License 2.0.

let f32 = new Float32Array(1)
let f32_u8 = new Uint8Array(f32.buffer)

let f64 = new Float64Array(1)
let f64_u8 = new Uint8Array(f64.buffer)

function intToLong(value: number): Long {
  value |= 0
  return {
    low: value,
    high: value >> 31,
    unsigned: value >= 0,
  }
}

let bbStack: ByteBuffer[] = []

function popByteBuffer(): ByteBuffer {
  const bb = bbStack.pop()
  if (!bb) return { bytes: new Uint8Array(64), offset: 0, limit: 0 }
  bb.offset = bb.limit = 0
  return bb
}

function pushByteBuffer(bb: ByteBuffer): void {
  bbStack.push(bb)
}

function wrapByteBuffer(bytes: Uint8Array): ByteBuffer {
  return { bytes, offset: 0, limit: bytes.length }
}

function toUint8Array(bb: ByteBuffer): Uint8Array {
  let bytes = bb.bytes
  let limit = bb.limit
  return bytes.length === limit ? bytes : bytes.subarray(0, limit)
}

function skip(bb: ByteBuffer, offset: number): void {
  if (bb.offset + offset > bb.limit) {
    throw new Error('Skip past limit')
  }
  bb.offset += offset
}

function isAtEnd(bb: ByteBuffer): boolean {
  return bb.offset >= bb.limit
}

function grow(bb: ByteBuffer, count: number): number {
  let bytes = bb.bytes
  let offset = bb.offset
  let limit = bb.limit
  let finalOffset = offset + count
  if (finalOffset > bytes.length) {
    let newBytes = new Uint8Array(finalOffset * 2)
    newBytes.set(bytes)
    bb.bytes = newBytes
  }
  bb.offset = finalOffset
  if (finalOffset > limit) {
    bb.limit = finalOffset
  }
  return offset
}

function advance(bb: ByteBuffer, count: number): number {
  let offset = bb.offset
  if (offset + count > bb.limit) {
    throw new Error('Read past limit')
  }
  bb.offset += count
  return offset
}

function readBytes(bb: ByteBuffer, count: number): Uint8Array {
  let offset = advance(bb, count)
  return bb.bytes.subarray(offset, offset + count)
}

function writeBytes(bb: ByteBuffer, buffer: Uint8Array): void {
  let offset = grow(bb, buffer.length)
  bb.bytes.set(buffer, offset)
}

function readString(bb: ByteBuffer, count: number): string {
  // Sadly a hand-coded UTF8 decoder is much faster than subarray+TextDecoder in V8
  let offset = advance(bb, count)
  let fromCharCode = String.fromCharCode
  let bytes = bb.bytes
  let invalid = '\uFFFD'
  let text = ''

  for (let i = 0; i < count; i++) {
    let c1 = bytes[i + offset],
      c2: number,
      c3: number,
      c4: number,
      c: number

    // 1 byte
    if ((c1 & 0x80) === 0) {
      text += fromCharCode(c1)
    }

    // 2 bytes
    else if ((c1 & 0xe0) === 0xc0) {
      if (i + 1 >= count) text += invalid
      else {
        c2 = bytes[i + offset + 1]
        if ((c2 & 0xc0) !== 0x80) text += invalid
        else {
          c = ((c1 & 0x1f) << 6) | (c2 & 0x3f)
          if (c < 0x80) text += invalid
          else {
            text += fromCharCode(c)
            i++
          }
        }
      }
    }

    // 3 bytes
    else if ((c1 & 0xf0) == 0xe0) {
      if (i + 2 >= count) text += invalid
      else {
        c2 = bytes[i + offset + 1]
        c3 = bytes[i + offset + 2]
        if (((c2 | (c3 << 8)) & 0xc0c0) !== 0x8080) text += invalid
        else {
          c = ((c1 & 0x0f) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f)
          if (c < 0x0800 || (c >= 0xd800 && c <= 0xdfff)) text += invalid
          else {
            text += fromCharCode(c)
            i += 2
          }
        }
      }
    }

    // 4 bytes
    else if ((c1 & 0xf8) == 0xf0) {
      if (i + 3 >= count) text += invalid
      else {
        c2 = bytes[i + offset + 1]
        c3 = bytes[i + offset + 2]
        c4 = bytes[i + offset + 3]
        if (((c2 | (c3 << 8) | (c4 << 16)) & 0xc0c0c0) !== 0x808080) text += invalid
        else {
          c = ((c1 & 0x07) << 0x12) | ((c2 & 0x3f) << 0x0c) | ((c3 & 0x3f) << 0x06) | (c4 & 0x3f)
          if (c < 0x10000 || c > 0x10ffff) text += invalid
          else {
            c -= 0x10000
            text += fromCharCode((c >> 10) + 0xd800, (c & 0x3ff) + 0xdc00)
            i += 3
          }
        }
      }
    } else text += invalid
  }

  return text
}

function writeString(bb: ByteBuffer, text: string): void {
  // Sadly a hand-coded UTF8 encoder is much faster than TextEncoder+set in V8
  let n = text.length
  let byteCount = 0

  // Write the byte count first
  for (let i = 0; i < n; i++) {
    let c = text.charCodeAt(i)
    if (c >= 0xd800 && c <= 0xdbff && i + 1 < n) {
      c = (c << 10) + text.charCodeAt(++i) - 0x35fdc00
    }
    byteCount += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4
  }
  writeVarint32(bb, byteCount)

  let offset = grow(bb, byteCount)
  let bytes = bb.bytes

  // Then write the bytes
  for (let i = 0; i < n; i++) {
    let c = text.charCodeAt(i)
    if (c >= 0xd800 && c <= 0xdbff && i + 1 < n) {
      c = (c << 10) + text.charCodeAt(++i) - 0x35fdc00
    }
    if (c < 0x80) {
      bytes[offset++] = c
    } else {
      if (c < 0x800) {
        bytes[offset++] = ((c >> 6) & 0x1f) | 0xc0
      } else {
        if (c < 0x10000) {
          bytes[offset++] = ((c >> 12) & 0x0f) | 0xe0
        } else {
          bytes[offset++] = ((c >> 18) & 0x07) | 0xf0
          bytes[offset++] = ((c >> 12) & 0x3f) | 0x80
        }
        bytes[offset++] = ((c >> 6) & 0x3f) | 0x80
      }
      bytes[offset++] = (c & 0x3f) | 0x80
    }
  }
}

function writeByteBuffer(bb: ByteBuffer, buffer: ByteBuffer): void {
  let offset = grow(bb, buffer.limit)
  let from = bb.bytes
  let to = buffer.bytes

  // This for loop is much faster than subarray+set on V8
  for (let i = 0, n = buffer.limit; i < n; i++) {
    from[i + offset] = to[i]
  }
}

function readByte(bb: ByteBuffer): number {
  return bb.bytes[advance(bb, 1)]
}

function writeByte(bb: ByteBuffer, value: number): void {
  let offset = grow(bb, 1)
  bb.bytes[offset] = value
}

function readFloat(bb: ByteBuffer): number {
  let offset = advance(bb, 4)
  let bytes = bb.bytes

  // Manual copying is much faster than subarray+set in V8
  f32_u8[0] = bytes[offset++]
  f32_u8[1] = bytes[offset++]
  f32_u8[2] = bytes[offset++]
  f32_u8[3] = bytes[offset++]
  return f32[0]
}

function writeFloat(bb: ByteBuffer, value: number): void {
  let offset = grow(bb, 4)
  let bytes = bb.bytes
  f32[0] = value

  // Manual copying is much faster than subarray+set in V8
  bytes[offset++] = f32_u8[0]
  bytes[offset++] = f32_u8[1]
  bytes[offset++] = f32_u8[2]
  bytes[offset++] = f32_u8[3]
}

function readDouble(bb: ByteBuffer): number {
  let offset = advance(bb, 8)
  let bytes = bb.bytes

  // Manual copying is much faster than subarray+set in V8
  f64_u8[0] = bytes[offset++]
  f64_u8[1] = bytes[offset++]
  f64_u8[2] = bytes[offset++]
  f64_u8[3] = bytes[offset++]
  f64_u8[4] = bytes[offset++]
  f64_u8[5] = bytes[offset++]
  f64_u8[6] = bytes[offset++]
  f64_u8[7] = bytes[offset++]
  return f64[0]
}

function writeDouble(bb: ByteBuffer, value: number): void {
  let offset = grow(bb, 8)
  let bytes = bb.bytes
  f64[0] = value

  // Manual copying is much faster than subarray+set in V8
  bytes[offset++] = f64_u8[0]
  bytes[offset++] = f64_u8[1]
  bytes[offset++] = f64_u8[2]
  bytes[offset++] = f64_u8[3]
  bytes[offset++] = f64_u8[4]
  bytes[offset++] = f64_u8[5]
  bytes[offset++] = f64_u8[6]
  bytes[offset++] = f64_u8[7]
}

function readInt32(bb: ByteBuffer): number {
  let offset = advance(bb, 4)
  let bytes = bb.bytes
  return bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)
}

function writeInt32(bb: ByteBuffer, value: number): void {
  let offset = grow(bb, 4)
  let bytes = bb.bytes
  bytes[offset] = value
  bytes[offset + 1] = value >> 8
  bytes[offset + 2] = value >> 16
  bytes[offset + 3] = value >> 24
}

function readInt64(bb: ByteBuffer, unsigned: boolean): Long {
  return {
    low: readInt32(bb),
    high: readInt32(bb),
    unsigned,
  }
}

function writeInt64(bb: ByteBuffer, value: Long): void {
  writeInt32(bb, value.low)
  writeInt32(bb, value.high)
}

function readVarint32(bb: ByteBuffer): number {
  let c = 0
  let value = 0
  let b: number
  do {
    b = readByte(bb)
    if (c < 32) value |= (b & 0x7f) << c
    c += 7
  } while (b & 0x80)
  return value
}

function writeVarint32(bb: ByteBuffer, value: number): void {
  value >>>= 0
  while (value >= 0x80) {
    writeByte(bb, (value & 0x7f) | 0x80)
    value >>>= 7
  }
  writeByte(bb, value)
}

function readVarint64(bb: ByteBuffer, unsigned: boolean): Long {
  let part0 = 0
  let part1 = 0
  let part2 = 0
  let b: number

  b = readByte(bb)
  part0 = b & 0x7f
  if (b & 0x80) {
    b = readByte(bb)
    part0 |= (b & 0x7f) << 7
    if (b & 0x80) {
      b = readByte(bb)
      part0 |= (b & 0x7f) << 14
      if (b & 0x80) {
        b = readByte(bb)
        part0 |= (b & 0x7f) << 21
        if (b & 0x80) {
          b = readByte(bb)
          part1 = b & 0x7f
          if (b & 0x80) {
            b = readByte(bb)
            part1 |= (b & 0x7f) << 7
            if (b & 0x80) {
              b = readByte(bb)
              part1 |= (b & 0x7f) << 14
              if (b & 0x80) {
                b = readByte(bb)
                part1 |= (b & 0x7f) << 21
                if (b & 0x80) {
                  b = readByte(bb)
                  part2 = b & 0x7f
                  if (b & 0x80) {
                    b = readByte(bb)
                    part2 |= (b & 0x7f) << 7
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  return {
    low: part0 | (part1 << 28),
    high: (part1 >>> 4) | (part2 << 24),
    unsigned,
  }
}

function writeVarint64(bb: ByteBuffer, value: Long): void {
  let part0 = value.low >>> 0
  let part1 = ((value.low >>> 28) | (value.high << 4)) >>> 0
  let part2 = value.high >>> 24

  // ref: src/google/protobuf/io/coded_stream.cc
  let size =
    part2 === 0
      ? part1 === 0
        ? part0 < 1 << 14
          ? part0 < 1 << 7
            ? 1
            : 2
          : part0 < 1 << 21
          ? 3
          : 4
        : part1 < 1 << 14
        ? part1 < 1 << 7
          ? 5
          : 6
        : part1 < 1 << 21
        ? 7
        : 8
      : part2 < 1 << 7
      ? 9
      : 10

  let offset = grow(bb, size)
  let bytes = bb.bytes

  switch (size) {
    case 10:
      bytes[offset + 9] = (part2 >>> 7) & 0x01
    case 9:
      bytes[offset + 8] = size !== 9 ? part2 | 0x80 : part2 & 0x7f
    case 8:
      bytes[offset + 7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7f
    case 7:
      bytes[offset + 6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7f
    case 6:
      bytes[offset + 5] = size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7f
    case 5:
      bytes[offset + 4] = size !== 5 ? part1 | 0x80 : part1 & 0x7f
    case 4:
      bytes[offset + 3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7f
    case 3:
      bytes[offset + 2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7f
    case 2:
      bytes[offset + 1] = size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7f
    case 1:
      bytes[offset] = size !== 1 ? part0 | 0x80 : part0 & 0x7f
  }
}

function readVarint32ZigZag(bb: ByteBuffer): number {
  let value = readVarint32(bb)

  // ref: src/google/protobuf/wire_format_lite.h
  return (value >>> 1) ^ -(value & 1)
}

function writeVarint32ZigZag(bb: ByteBuffer, value: number): void {
  // ref: src/google/protobuf/wire_format_lite.h
  writeVarint32(bb, (value << 1) ^ (value >> 31))
}

function readVarint64ZigZag(bb: ByteBuffer): Long {
  let value = readVarint64(bb, /* unsigned */ false)
  let low = value.low
  let high = value.high
  let flip = -(low & 1)

  // ref: src/google/protobuf/wire_format_lite.h
  return {
    low: ((low >>> 1) | (high << 31)) ^ flip,
    high: (high >>> 1) ^ flip,
    unsigned: false,
  }
}

function writeVarint64ZigZag(bb: ByteBuffer, value: Long): void {
  let low = value.low
  let high = value.high
  let flip = high >> 31

  // ref: src/google/protobuf/wire_format_lite.h
  writeVarint64(bb, {
    low: (low << 1) ^ flip,
    high: ((high << 1) | (low >>> 31)) ^ flip,
    unsigned: false,
  })
}
export interface SegyHeader {
  textHeader?: string
  binaryHeader?: BinaryHeader
  stats?: Stats
}

export function encodeSegyHeader(message: SegyHeader): Uint8Array {
  let bb = popByteBuffer()
  _encodeSegyHeader(message, bb)
  return toUint8Array(bb)
}
  1. Interfaces
  2. Encode
  3. Decode
  4. A whole bunch of parsing
import { encodeSegyHeader } from 'segy.ts'

const parsed = parseSegyToBin(rawSegyFile)
const encodedSH = encodeSegyHeader(parsed)

const segyHeaderUpload = s3
.upload({
  Key: encodedSHPath,
  Bucket,
  Body: encodedSH,
})
.promise()
import {  decodeSegyHeader } from 'segy.ts'

async function fetchSegyHeader(segyHeaderURL: string) {
  return fetch(segyHeaderURL, {
    headers: { 'Content-Type': 'application/octet-stream' },
  })
    .then((res) => res.arrayBuffer())
    .then((data) => decodeSegyHeader(new Uint8Array(data)))
}

1

2

3

Encode

Store

Retrieve

Did it work out?

Handwave:

This is Just the transport layer!

  • 3d in browser optimization (Babylon JS)

  • Canvas Optimization

  • React Optimization

  • Parsing Optimization

  • AWS Lambda/ s3/EventBridge Optimization

  • Downsampling

44.1 Million Data Points

gRPC

You can't really mention Protobufs

without also mentioning gRPC

  • Rewrite of Google's internal tool Stubby
  • First written with microservices in mind
  • Supported in basically every language
  • Uses Http/2 (2015)
  • ... multiplexing over 1 TCP
  • And Http/3 (soon? cloudflare can do it, somehow)

gRPC

differnt from..

  • graphQL
  • REST
  • SOAP
  • tRPC

gRPC

remote procedure call! Send a message and invoke a function

1

RPC

The Protobufs. The part we just covered

2

Message

The (namespaced) container that glues the RPC functions to the Messages

3

Service

syntax = "proto3";

//nothing new here
message HelloThereRequest {
  string name = 1;
}

//or here
message HelloThereReply {
  string message = 1;
}

//the new thing.
service HelloThereService {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {}
}

gRPC

Browser gRPC

Buf

Connect

service ElizaService {
  rpc Say(SayRequest) returns (SayResponse) {}
}
const answer = await eliza.say({sentence: "I feel happy."});
console.log(answer);
// {sentence: 'When you feel happy, what do you do?'}
  1. React
  2. Svelte
  3. Next
  4. Angular

More Resources:

Thank You!

Questions?

twitter        @5imian

github        the-simian

soundcloud  the simian

email         info@simiancraft.com

site           simiancraft.com

               jesseharlin.net

 

Protobufs and More

By Jesse Harlin

Protobufs and More

  • 847