[GODRIVER-632] Add As* methods to bsoncore.Value, bson.RawValue, and bson.Val types Created: 09/Nov/18  Updated: 07/Feb/23  Resolved: 06/Feb/23

Status: Closed
Project: Go Driver
Component/s: BSON
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major - P3
Reporter: Kristofer Brandow (Inactive) Assignee: Unassigned
Resolution: Won't Do Votes: 0
Labels: neweng
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to GODRIVER-413 Implement Improved BSON Design Closed
related to GODRIVER-610 Scope & Design Improved BSON Support Closed
is related to GODRIVER-2167 Deprecate frequently lossy "bson.RawV... Closed
Documentation Changes Summary:

1. What would you like to communicate to the user about this feature?
2. Would you like the user to see examples of the syntax and/or executable code and its output?
3. Which versions of the driver/connector does this apply to?


 Description   

Numeric BSON value types can be difficult to deal with. Depending on the source, a number might be a float64, int32, int64, or decimal128. To ease the usability of the Value types, add As*  and As*OK methods to each value type for float64, int32, and int64.



 Comments   
Comment by Matt Dale [ 07/Feb/23 ]

Adding more detail about why we decided to close this:

Conversion between numeric types can be silently lossy in non-intuitive ways, so we should limit the ability to silently lose data in the As* APIs. Specifically, the following BSON numeric type conversion cases are lossy:

  • Converting a BSON "double" (64-bit float) into a Go int32 will silently lose data for values:
    • Any value with a fractional part (truncates the fractional part)
    • Greater than math.MaxInt32 (returns math.MinInt32)
    • Less than math.MinInt32 (returns math.MinInt32)
    • NaN, +Inf, -Inf (returns math.MinInt32)
  • Converting a BSON "double" (64-bit float) into a Go int64 will silently lose data for values:
    • Any value with a fractional part (truncates the fractional part)
    • Greater than math.MaxInt64 (returns math.MinInt64)
    • Less than math.MinInt64 (returns math.MinInt64)
    • NaN, +Inf, -Inf
  • Converting a BSON "int64" (64-bit integer) into a Go int32 will silently lose data for values:
    • Greater than math.MaxInt32 (overflow and flip sign)
    • Less than math.MinInt32 (overflow and flip sign)
  • Converting a BSON "int64" (64-bit integer) into a Go float64 will silently lose data for values:
    • Greater than 2^53 (lose integer precision)
    • Less than -1 * 2^53 (lose integer precision)

Converting BSON "decimal128" to native Go types is even less intuitive and should be avoided.

Since we know the cases where we'll lose data, it's possible we can allow conversion when it isn't lossy (which is true for many every-day values). For reference, bson.Unmarshall does allow converting between int <-> float when there is no truncation, but does not catch precision errors for too-large integer values.

Generated at Thu Feb 08 08:34:37 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.