forked from mongodb/mongo-go-driver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wiremessage.go
203 lines (175 loc) · 6.19 KB
/
wiremessage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// 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 wiremessage contains types for speaking the MongoDB Wire Protocol. Since this low
// level library is meant to be used in the context of a driver and in the context of a server
// all of the flags and types of the wire protocol are implemented. For each op there are two
// corresponding implementations. One prefixed with Immutable which can be created by casting a
// []byte to the type, and another prefixed with Mutable that is a struct with methods to mutate
// the op.
package wiremessage
import (
"context"
"errors"
"fmt"
"io"
"sync/atomic"
)
// ErrInvalidMessageLength is returned when the provided message length is too small to be valid.
var ErrInvalidMessageLength = errors.New("the message length is too small, it must be at least 16")
// ErrUnknownOpCode is returned when the provided opcode is not a valid opcode.
var ErrUnknownOpCode = errors.New("the opcode is unknown")
var globalRequestID int32
// CurrentRequestID returns the current request ID.
func CurrentRequestID() int32 { return atomic.LoadInt32(&globalRequestID) }
// NextRequestID returns the next request ID.
func NextRequestID() int32 { return atomic.AddInt32(&globalRequestID, 1) }
// Error represents an error related to wire protocol messages.
type Error struct {
Type ErrorType
Message string
}
// Error implements the err interface.
func (e Error) Error() string {
return e.Message
}
// ErrorType is the type of error, which indicates from which part of the code
// the error originated.
type ErrorType uint16
// These constants are the types of errors exposed by this package.
const (
ErrNil ErrorType = iota
ErrHeader
ErrOpQuery
ErrOpReply
)
// OpCode represents a MongoDB wire protocol opcode.
type OpCode int32
// These constants are the valid opcodes for the version of the wireprotocol
// supported by this library. The skipped OpCodes are historical OpCodes that
// are no longer used.
const (
OpReply OpCode = 1
_ OpCode = 1001
OpUpdate OpCode = 2001
OpInsert OpCode = 2002
_ OpCode = 2003
OpQuery OpCode = 2004
OpGetMore OpCode = 2005
OpDelete OpCode = 2006
OpKillCursors OpCode = 2007
OpCommand OpCode = 2010
OpCommandReply OpCode = 2011
OpCompressed OpCode = 2012
OpMsg OpCode = 2013
)
// String implements the fmt.Stringer interface.
func (oc OpCode) String() string {
switch oc {
case OpReply:
return "OP_REPLY"
case OpUpdate:
return "OP_UPDATE"
case OpInsert:
return "OP_INSERT"
case OpQuery:
return "OP_QUERY"
case OpGetMore:
return "OP_GET_MORE"
case OpDelete:
return "OP_DELETE"
case OpKillCursors:
return "OP_KILL_CURSORS"
case OpCommand:
return "OP_COMMAND"
case OpCommandReply:
return "OP_COMMANDREPLY"
case OpCompressed:
return "OP_COMPRESSED"
case OpMsg:
return "OP_MSG"
default:
return "<invalid opcode>"
}
}
// WireMessage represents a message in the MongoDB wire protocol.
type WireMessage interface {
Marshaler
Validator
Appender
fmt.Stringer
// Len returns the length in bytes of this WireMessage.
Len() int
}
// Validator is the interface implemented by types that can validate
// themselves as a MongoDB wire protocol message.
type Validator interface {
ValidateWireMessage() error
}
// Marshaler is the interface implemented by types that can marshal
// themselves into a valid MongoDB wire protocol message.
type Marshaler interface {
MarshalWireMessage() ([]byte, error)
}
// Appender is the interface implemented by types that can append themselves, as
// a MongoDB wire protocol message, to the provided slice of bytes.
type Appender interface {
AppendWireMessage([]byte) ([]byte, error)
}
// Unmarshaler is the interface implemented by types that can unmarshal a
// MongoDB wire protocol message version of themselves. The input can be
// assumed to be a valid MongoDB wire protocol message. UnmarshalWireMessage
// must copy the data if it wishes to retain the data after returning.
type Unmarshaler interface {
UnmarshalWireMessage([]byte) error
}
// Writer is the interface implemented by types that can have WireMessages
// written to them.
//
// Implementation must obey the cancellation, timeouts, and deadlines of the
// provided context.Context object.
type Writer interface {
WriteWireMessage(context.Context, WireMessage) error
}
// Reader is the interface implemented by types that can have WireMessages
// read from them.
//
// Implementation must obey the cancellation, timeouts, and deadlines of the
// provided context.Context object.
type Reader interface {
ReadWireMessage(context.Context) (WireMessage, error)
}
// ReadWriter is the interface implemented by types that can both read and write
// WireMessages.
type ReadWriter interface {
Reader
Writer
}
// ReadWriteCloser is the interface implemented by types that can read and write
// WireMessages and can also be closed.
type ReadWriteCloser interface {
Reader
Writer
io.Closer
}
// Transformer is the interface implemented by types that can alter a WireMessage.
// Implementations should not directly alter the provided WireMessage and instead
// make a copy of the message, alter it, and returned the new message.
type Transformer interface {
TransformWireMessage(WireMessage) (WireMessage, error)
}
// ReadFrom will read a single WireMessage from the given io.Reader. This function will
// validate the WireMessage. If the WireMessage is not valid, this method will
// return both the error and the invalid WireMessage. If another type of processing
// error occurs, WireMessage will be nil.
//
// This function will return the immutable versions of wire protocol messages. The
// Convert function can be used to retrieve a mutable version of wire protocol
// messages.
func ReadFrom(io.Reader) (WireMessage, error) { return nil, nil }
// Unmarshal will unmarshal data into a WireMessage.
func Unmarshal([]byte) (WireMessage, error) { return nil, nil }
// Validate will validate that data is a valid MongoDB wire protocol message.
func Validate([]byte) error { return nil }