@@ -3,13 +3,60 @@ import {
3
3
BSONType ,
4
4
type Document ,
5
5
Long ,
6
+ parseToElementsToArray ,
6
7
type Timestamp
7
8
} from '../../bson' ;
8
9
import { MongoUnexpectedServerResponseError } from '../../error' ;
9
10
import { type ClusterTime } from '../../sdam/common' ;
10
11
import { type MongoDBNamespace , ns } from '../../utils' ;
11
12
import { OnDemandDocument } from './on_demand/document' ;
12
13
14
+ // eslint-disable-next-line no-restricted-syntax
15
+ const enum BSONElementOffset {
16
+ type = 0 ,
17
+ nameOffset = 1 ,
18
+ nameLength = 2 ,
19
+ offset = 3 ,
20
+ length = 4
21
+ }
22
+ /**
23
+ * Accepts a BSON payload and checks for na "ok: 0" element.
24
+ * This utility is intended to prevent calling response class constructors
25
+ * that expect the result to be a success and demand certain properties to exist.
26
+ *
27
+ * For example, a cursor response always expects a cursor embedded document.
28
+ * In order to write the class such that the properties reflect that assertion (non-null)
29
+ * we cannot invoke the subclass constructor if the BSON represents an error.
30
+ *
31
+ * @param bytes - BSON document returned from the server
32
+ */
33
+ export function isErrorResponse ( bson : Uint8Array ) : boolean {
34
+ const elements = parseToElementsToArray ( bson , 0 ) ;
35
+ for ( let eIdx = 0 ; eIdx < elements . length ; eIdx ++ ) {
36
+ const element = elements [ eIdx ] ;
37
+
38
+ if ( element [ BSONElementOffset . nameLength ] === 2 ) {
39
+ const nameOffset = element [ BSONElementOffset . nameOffset ] ;
40
+
41
+ // 111 == "o", 107 == "k"
42
+ if ( bson [ nameOffset ] === 111 && bson [ nameOffset + 1 ] === 107 ) {
43
+ const valueOffset = element [ BSONElementOffset . offset ] ;
44
+ const valueLength = element [ BSONElementOffset . length ] ;
45
+
46
+ // If any byte in the length of the ok number (works for any type) is non zero,
47
+ // then it is considered "ok: 1"
48
+ for ( let i = valueOffset ; i < valueOffset + valueLength ; i ++ ) {
49
+ if ( bson [ i ] !== 0x00 ) return false ;
50
+ }
51
+
52
+ return true ;
53
+ }
54
+ }
55
+ }
56
+
57
+ return true ;
58
+ }
59
+
13
60
/** @internal */
14
61
export type MongoDBResponseConstructor = {
15
62
new ( bson : Uint8Array , offset ?: number , isArray ?: boolean ) : MongoDBResponse ;
@@ -142,18 +189,16 @@ export class CursorResponse extends MongoDBResponse {
142
189
return value instanceof CursorResponse ;
143
190
}
144
191
145
- public id : Long | null = null ;
146
- public ns : MongoDBNamespace | null = null ;
192
+ public id : Long ;
193
+ public ns : MongoDBNamespace ;
147
194
public batchSize = 0 ;
148
195
149
- private batch : OnDemandDocument | null = null ;
196
+ private batch : OnDemandDocument ;
150
197
private iterated = 0 ;
151
198
152
199
constructor ( bytes : Uint8Array , offset ?: number , isArray ?: boolean ) {
153
200
super ( bytes , offset , isArray ) ;
154
201
155
- if ( this . isError ) return ;
156
-
157
202
const cursor = this . get ( 'cursor' , BSONType . object , true ) ;
158
203
159
204
const id = cursor . get ( 'id' , BSONType . long , true ) ;
0 commit comments