wire: parse a logical session id out of a command body
An accessor over the command envelope, next to `db_name` and the same shape: called from dispatch, never from `parse`, because a malformed session id is a command that gets an error reply, not a connection that gets torn down. It returns the 16 bytes or names what is wrong; the codes stay in the command layer, where they were measured. The tolerated fields were measured against mongod 8.3.7 rather than recalled, and the measurement contradicted the assumption this was designed on. The design said unknown fields inside `lsid` would be tolerated, on the reasoning that the server tolerates unknown fields everywhere and pinpoint strictness would be inconsistent. mongod answers IDLUnknownField (40415) -- it is strict here and the reasoning was simply wrong. It also accepts `uid`, the hash of the credentials owning the session, which a driver starts sending the moment authentication is on; rejecting that would have broken every command in M7, and the test says so where a future reader will meet it. `txnNumber` and `txnUUID` inside `lsid` are refused. They are not the retryable-write `txnNumber` that sits outside it: together they name an *internal* session, one that runs a transaction on another session's behalf. mongod refuses them on a standalone too. Also `bson.Value.type_name`, which is mongod's name for a type rather than Zig's -- a TypeMismatch message quotes it, and a driver that matches on the text is matching on these. 170/170 unit tests.
This commit is contained in:
29
src/bson.zig
29
src/bson.zig
@@ -74,6 +74,35 @@ pub const Value = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
/// The name mongod uses for this type in a TypeMismatch message ("is the
|
||||
/// wrong type 'int', expected type 'object'"). Its own names, not Zig's:
|
||||
/// a driver that matches on the text is matching on these.
|
||||
pub fn type_name(self: Value) []const u8 {
|
||||
return switch (self) {
|
||||
.double => "double",
|
||||
.string => "string",
|
||||
.doc => "object",
|
||||
.array => "array",
|
||||
.binary => "binData",
|
||||
.object_id => "objectId",
|
||||
.bool => "bool",
|
||||
.datetime => "date",
|
||||
.null => "null",
|
||||
.regex => "regex",
|
||||
.code => "javascript",
|
||||
.symbol => "symbol",
|
||||
.int32 => "int",
|
||||
.timestamp => "timestamp",
|
||||
.int64 => "long",
|
||||
.decimal128 => "decimal",
|
||||
.min_key => "minKey",
|
||||
.max_key => "maxKey",
|
||||
// An unparsed value keeps only its tag byte, and the tags this
|
||||
// union does not name are the ones nothing here inspects.
|
||||
.opaque_val => "unknown",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn is_number(self: Value) bool {
|
||||
return switch (self) {
|
||||
.double, .int32, .int64 => true,
|
||||
|
||||
Reference in New Issue
Block a user