fix(nix): update vendorHash and vendor dir for new deps
This commit is contained in:
+135
@@ -0,0 +1,135 @@
|
||||
// Copyright (C) MongoDB, Inc. 2025-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Package binaryutil provides utility functions for working with binary data.
|
||||
package binaryutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// Append32 appends a uint32 or int32 value to dst in little-endian byte order.
|
||||
// Byte shifting is done directly to prevent overflow security errors, in
|
||||
// compliance with gosec G115.
|
||||
//
|
||||
// See: https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/encoding/binary/binary.go;l=92
|
||||
func Append32[T ~uint32 | ~int32](dst []byte, v T) []byte {
|
||||
return append(dst,
|
||||
byte(v),
|
||||
byte(v>>8),
|
||||
byte(v>>16),
|
||||
byte(v>>24),
|
||||
)
|
||||
}
|
||||
|
||||
// Append64 appends a uint64 or int64 value to dst in little-endian byte order.
|
||||
// Byte shifting is done directly to prevent overflow security errors, in
|
||||
// compliance with gosec G115.
|
||||
//
|
||||
// See: https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/encoding/binary/binary.go;l=119
|
||||
func Append64[T ~uint64 | ~int64](dst []byte, v T) []byte {
|
||||
return append(dst,
|
||||
byte(v),
|
||||
byte(v>>8),
|
||||
byte(v>>16),
|
||||
byte(v>>24),
|
||||
byte(v>>32),
|
||||
byte(v>>40),
|
||||
byte(v>>48),
|
||||
byte(v>>56),
|
||||
)
|
||||
}
|
||||
|
||||
// ReadU32 reads a uint32 from src in little-endian byte order. ReadU32 and
|
||||
// ReadI32 are separate functions to avoid unsafe casting between unsigned and
|
||||
// signed integers.
|
||||
func ReadU32(src []byte) (uint32, []byte, bool) {
|
||||
if len(src) < 4 {
|
||||
return 0, src, false
|
||||
}
|
||||
|
||||
return binary.LittleEndian.Uint32(src), src[4:], true
|
||||
}
|
||||
|
||||
// ReadI32 reads an int32 from src in little-endian byte order.
|
||||
// Byte shifting is done directly to prevent overflow security errors, in
|
||||
// compliance with gosec G115. ReadU32 and ReadI32 are separate functions to
|
||||
// avoid unsafe casting between unsigned and signed integers.
|
||||
//
|
||||
// See: https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/encoding/binary/binary.go;l=79
|
||||
func ReadI32(src []byte) (int32, []byte, bool) {
|
||||
if len(src) < 4 {
|
||||
return 0, src, false
|
||||
}
|
||||
|
||||
_ = src[3] // bounds check hint to compiler
|
||||
|
||||
value := int32(src[0]) |
|
||||
int32(src[1])<<8 |
|
||||
int32(src[2])<<16 |
|
||||
int32(src[3])<<24
|
||||
|
||||
return value, src[4:], true
|
||||
}
|
||||
|
||||
// ReadU64 reads a uint64 from src in little-endian byte order. ReadU64 and
|
||||
// ReadI64 are separate functions to avoid unsafe casting between unsigned and
|
||||
// signed integers.
|
||||
func ReadU64(src []byte) (uint64, []byte, bool) {
|
||||
if len(src) < 8 {
|
||||
return 0, src, false
|
||||
}
|
||||
|
||||
return binary.LittleEndian.Uint64(src), src[8:], true
|
||||
}
|
||||
|
||||
// ReadI64 reads an int64 from src in little-endian byte order.
|
||||
// Byte shifting is done directly to prevent overflow security errors, in
|
||||
// compliance with gosec G115. ReadU64 and ReadI64 are separate functions to
|
||||
// avoid unsafe casting between unsigned and signed integers.
|
||||
//
|
||||
// See: https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/encoding/binary/binary.go;l=101
|
||||
func ReadI64(src []byte) (int64, []byte, bool) {
|
||||
if len(src) < 8 {
|
||||
return 0, src, false
|
||||
}
|
||||
|
||||
_ = src[7] // bounds check hint to compiler
|
||||
|
||||
value := int64(src[0]) |
|
||||
int64(src[1])<<8 |
|
||||
int64(src[2])<<16 |
|
||||
int64(src[3])<<24 |
|
||||
int64(src[4])<<32 |
|
||||
int64(src[5])<<40 |
|
||||
int64(src[6])<<48 |
|
||||
int64(src[7])<<56
|
||||
|
||||
return value, src[8:], true
|
||||
}
|
||||
|
||||
// ReadCStringBytes reads a null-terminated C string from src as a byte slice.
|
||||
// This is the base implementation used by ReadCString to ensure a single source
|
||||
// of truth for C string parsing logic.
|
||||
func ReadCStringBytes(src []byte) ([]byte, []byte, bool) {
|
||||
idx := bytes.IndexByte(src, 0x00)
|
||||
if idx < 0 {
|
||||
return nil, src, false
|
||||
}
|
||||
return src[:idx], src[idx+1:], true
|
||||
}
|
||||
|
||||
// ReadCString reads a null-terminated C string from src as a string.
|
||||
// It delegates to ReadCStringBytes to maintain a single source of truth for
|
||||
// C string parsing logic.
|
||||
func ReadCString(src []byte) (string, []byte, bool) {
|
||||
cstr, rem, ok := ReadCStringBytes(src)
|
||||
if !ok {
|
||||
return "", src, false
|
||||
}
|
||||
return string(cstr), rem, true
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) MongoDB, Inc. 2026-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Package binaryutil provides functions for reading binary primitives from
|
||||
// byte slices. It is used internally for BSON parsing and wire protocol
|
||||
// operations.
|
||||
//
|
||||
// The functions in this package are designed for use in BSON operations.
|
||||
// Signed integer functions (ReadI32, ReadI64) use manual bit-shifting rather
|
||||
// than encoding/binary to avoid unsafe signed/unsigned conversions and comply
|
||||
// with gosec G115. Bounds-check elimination (BCE) hints help the compiler
|
||||
// inline these functions.
|
||||
//
|
||||
// Benchmarking across different ARM64 architectures (Apple M-series)
|
||||
// revealed non-deterministic performance discrepancies between using the
|
||||
// "encoding/binary" standard library and manual bit-shifting ("straight-lining").
|
||||
//
|
||||
// Without Loss of Generality (WLOG), benchmarking observed that:
|
||||
// - On Apple M1 Pro: Standard library (ReadU32) outperformed manual
|
||||
// bit-shifting (ReadI32) by ~2x (~0.08ns vs ~0.16ns).
|
||||
// - On Apple M4 Max: Manual bit-shifting (ReadI32) outperformed the
|
||||
// standard library (ReadU32) by ~1.6x (~0.03ns vs ~0.05ns).
|
||||
//
|
||||
// Further testing showed that "straight-lining" the ReadU32 implementation
|
||||
// to match ReadI32 normalized performance to ~0.03ns on the M4 Max, even
|
||||
// though the generated assembly for both approaches is virtually equivalent.
|
||||
//
|
||||
// The generated assembly is nearly identical for both approaches. These
|
||||
// sub-nanosecond variations likely stem from microarchitecture differences
|
||||
// (instruction caching, branch prediction) rather than the code itself.
|
||||
//
|
||||
// Since network I/O dominates driver latency, these differences do not have a
|
||||
// significant impact on driver performance. The implementation favors security
|
||||
// compliance and readability over hardware-specific tuning.
|
||||
package binaryutil
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright (C) MongoDB, Inc. 2024-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package bsoncoreutil
|
||||
|
||||
// Truncate truncates a given string for a certain width
|
||||
func Truncate(str string, width int) string {
|
||||
if width <= 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(str) <= width {
|
||||
return str
|
||||
}
|
||||
|
||||
// Truncate the byte slice of the string to the given width.
|
||||
newStr := str[:width]
|
||||
|
||||
// Check if the last byte is at the beginning of a multi-byte character.
|
||||
// If it is, then remove the last byte.
|
||||
if newStr[len(newStr)-1]&0xC0 == 0xC0 {
|
||||
return newStr[:len(newStr)-1]
|
||||
}
|
||||
|
||||
// Check if the last byte is a multi-byte character
|
||||
if newStr[len(newStr)-1]&0xC0 == 0x80 {
|
||||
// If it is, step back until you we are at the start of a character
|
||||
for i := len(newStr) - 1; i >= 0; i-- {
|
||||
if newStr[i]&0xC0 == 0xC0 {
|
||||
// Truncate at the end of the character before the character we stepped back to
|
||||
return newStr[:i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newStr
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
// Copyright (C) MongoDB, Inc. 2017-present.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package decimal128
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// These constants are the maximum and minimum values for the exponent field in a decimal128 value.
|
||||
const (
|
||||
MaxDecimal128Exp = 6111
|
||||
MinDecimal128Exp = -6176
|
||||
)
|
||||
|
||||
func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) {
|
||||
div64 := uint64(div)
|
||||
a := h >> 32
|
||||
aq := a / div64
|
||||
ar := a % div64
|
||||
b := ar<<32 + h&(1<<32-1)
|
||||
bq := b / div64
|
||||
br := b % div64
|
||||
c := br<<32 + l>>32
|
||||
cq := c / div64
|
||||
cr := c % div64
|
||||
d := cr<<32 + l&(1<<32-1)
|
||||
dq := d / div64
|
||||
dr := d % div64
|
||||
return (aq<<32 | bq), (cq<<32 | dq), uint32(dr)
|
||||
}
|
||||
|
||||
// String returns a string representation of the decimal value.
|
||||
func String(h, l uint64) string {
|
||||
var posSign int // positive sign
|
||||
var exp int // exponent
|
||||
var high, low uint64 // significand high/low
|
||||
|
||||
if h>>63&1 == 0 {
|
||||
posSign = 1
|
||||
}
|
||||
|
||||
switch h >> 58 & (1<<5 - 1) {
|
||||
case 0x1F:
|
||||
return "NaN"
|
||||
case 0x1E:
|
||||
return "-Infinity"[posSign:]
|
||||
}
|
||||
|
||||
low = l
|
||||
if h>>61&3 == 3 {
|
||||
// Bits: 1*sign 2*ignored 14*exponent 111*significand.
|
||||
// Implicit 0b100 prefix in significand.
|
||||
exp = int(h >> 47 & (1<<14 - 1))
|
||||
// Spec says all of these values are out of range.
|
||||
high, low = 0, 0
|
||||
} else {
|
||||
// Bits: 1*sign 14*exponent 113*significand
|
||||
exp = int(h >> 49 & (1<<14 - 1))
|
||||
high = h & (1<<49 - 1)
|
||||
}
|
||||
exp += MinDecimal128Exp
|
||||
|
||||
// Would be handled by the logic below, but that's trivial and common.
|
||||
if high == 0 && low == 0 && exp == 0 {
|
||||
return "-0"[posSign:]
|
||||
}
|
||||
|
||||
var repr [48]byte // Loop 5 times over 9 digits plus dot, negative sign, and leading zero.
|
||||
last := len(repr)
|
||||
i := len(repr)
|
||||
dot := len(repr) + exp
|
||||
var rem uint32
|
||||
Loop:
|
||||
for d9 := 0; d9 < 5; d9++ {
|
||||
high, low, rem = divmod(high, low, 1e9)
|
||||
for d1 := 0; d1 < 9; d1++ {
|
||||
// Handle "-0.0", "0.00123400", "-1.00E-6", "1.050E+3", etc.
|
||||
if i < len(repr) && (dot == i || low == 0 && high == 0 && rem > 0 && rem < 10 && (dot < i-6 || exp > 0)) {
|
||||
exp += len(repr) - i
|
||||
i--
|
||||
repr[i] = '.'
|
||||
last = i - 1
|
||||
dot = len(repr) // Unmark.
|
||||
}
|
||||
c := '0' + byte(rem%10)
|
||||
rem /= 10
|
||||
i--
|
||||
repr[i] = c
|
||||
// Handle "0E+3", "1E+3", etc.
|
||||
if low == 0 && high == 0 && rem == 0 && i == len(repr)-1 && (dot < i-5 || exp > 0) {
|
||||
last = i
|
||||
break Loop
|
||||
}
|
||||
if c != '0' {
|
||||
last = i
|
||||
}
|
||||
// Break early. Works without it, but why.
|
||||
if dot > i && low == 0 && high == 0 && rem == 0 {
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
repr[last-1] = '-'
|
||||
last--
|
||||
|
||||
if exp > 0 {
|
||||
return string(repr[last+posSign:]) + "E+" + strconv.Itoa(exp)
|
||||
}
|
||||
if exp < 0 {
|
||||
return string(repr[last+posSign:]) + "E" + strconv.Itoa(exp)
|
||||
}
|
||||
return string(repr[last+posSign:])
|
||||
}
|
||||
Reference in New Issue
Block a user