Skip to content

Commit c4811ce

Browse files
authored
RUST-1827 remove generic parameter to Command (#1105)
1 parent d895a6d commit c4811ce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+331
-297
lines changed

src/bson_util.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use std::{
2+
collections::HashSet,
23
convert::TryFrom,
34
io::{Read, Write},
45
};
56

7+
use serde::Serialize;
8+
69
use crate::{
710
bson::{
811
oid::ObjectId,
@@ -15,7 +18,7 @@ use crate::{
1518
RawDocumentBuf,
1619
},
1720
checked::Checked,
18-
error::{ErrorKind, Result},
21+
error::{Error, ErrorKind, Result},
1922
runtime::SyncLittleEndianRead,
2023
};
2124

@@ -65,6 +68,13 @@ pub(crate) fn to_raw_bson_array(docs: &[Document]) -> Result<RawBson> {
6568
}
6669
Ok(RawBson::Array(array))
6770
}
71+
pub(crate) fn to_raw_bson_array_ser<T: Serialize>(values: &[T]) -> Result<RawBson> {
72+
let mut array = RawArrayBuf::new();
73+
for value in values {
74+
array.push(bson::to_raw_document_buf(value)?);
75+
}
76+
Ok(RawBson::Array(array))
77+
}
6878

6979
pub(crate) fn first_key(document: &Document) -> Option<&str> {
7080
document.keys().next().map(String::as_str)
@@ -162,13 +172,42 @@ pub(crate) fn extend_raw_document_buf(
162172
this: &mut RawDocumentBuf,
163173
other: RawDocumentBuf,
164174
) -> Result<()> {
175+
let mut keys: HashSet<String> = HashSet::new();
176+
for elem in this.iter_elements() {
177+
keys.insert(elem?.key().to_owned());
178+
}
165179
for result in other.iter() {
166180
let (k, v) = result?;
181+
if keys.contains(k) {
182+
return Err(Error::internal(format!(
183+
"duplicate raw document key {:?}",
184+
k
185+
)));
186+
}
167187
this.append(k, v.to_raw_bson());
168188
}
169189
Ok(())
170190
}
171191

192+
pub(crate) fn append_ser(
193+
this: &mut RawDocumentBuf,
194+
key: impl AsRef<str>,
195+
value: impl Serialize,
196+
) -> Result<()> {
197+
#[derive(Serialize)]
198+
struct Helper<T> {
199+
value: T,
200+
}
201+
let raw_doc = bson::to_raw_document_buf(&Helper { value })?;
202+
this.append_ref(
203+
key,
204+
raw_doc
205+
.get("value")?
206+
.ok_or_else(|| Error::internal("no value"))?,
207+
);
208+
Ok(())
209+
}
210+
172211
/// Returns the _id field of this document, prepending the field to the document if one is not
173212
/// already present.
174213
pub(crate) fn get_or_prepend_id_field(doc: &mut RawDocumentBuf) -> Result<Bson> {

src/client/auth.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod x509;
1414

1515
use std::{borrow::Cow, fmt::Debug, str::FromStr};
1616

17+
use bson::RawDocumentBuf;
1718
use derivative::Derivative;
1819
use hmac::{digest::KeyInit, Mac};
1920
use rand::Rng;
@@ -509,9 +510,9 @@ impl Credential {
509510

510511
/// If the mechanism is missing, append the appropriate mechanism negotiation key-value-pair to
511512
/// the provided hello or legacy hello command document.
512-
pub(crate) fn append_needed_mechanism_negotiation(&self, command: &mut Document) {
513+
pub(crate) fn append_needed_mechanism_negotiation(&self, command: &mut RawDocumentBuf) {
513514
if let (Some(username), None) = (self.username.as_ref(), self.mechanism.as_ref()) {
514-
command.insert(
515+
command.append(
515516
"saslSupportedMechs",
516517
format!("{}.{}", self.resolved_source(), username),
517518
);
@@ -613,7 +614,7 @@ pub(crate) enum ClientFirst {
613614
}
614615

615616
impl ClientFirst {
616-
pub(crate) fn to_document(&self) -> Document {
617+
pub(crate) fn to_document(&self) -> RawDocumentBuf {
617618
match self {
618619
Self::Scram(version, client_first) => client_first.to_command(version).body,
619620
Self::X509(command) => command.body.clone(),

src/client/auth/oidc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ fn make_spec_auth_command(
401401
payload: Vec<u8>,
402402
server_api: Option<&ServerApi>,
403403
) -> Command {
404-
let body = doc! {
404+
let body = rawdoc! {
405405
"saslStart": 1,
406406
"mechanism": MONGODB_OIDC_STR,
407407
"payload": Binary { subtype: BinarySubtype::Generic, bytes: payload },

src/client/auth/sasl.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use bson::{rawdoc, RawBson};
2+
13
use crate::{
2-
bson::{doc, spec::BinarySubtype, Binary, Bson, Document},
4+
bson::{spec::BinarySubtype, Binary, Bson, Document},
35
bson_util,
46
client::{auth::AuthMechanism, options::ServerApi},
57
cmap::Command,
@@ -31,15 +33,15 @@ impl SaslStart {
3133
}
3234

3335
pub(super) fn into_command(self) -> Command {
34-
let mut body = doc! {
36+
let mut body = rawdoc! {
3537
"saslStart": 1,
3638
"mechanism": self.mechanism.as_str(),
3739
"payload": Binary { subtype: BinarySubtype::Generic, bytes: self.payload },
3840
};
3941
if self.mechanism == AuthMechanism::ScramSha1
4042
|| self.mechanism == AuthMechanism::ScramSha256
4143
{
42-
body.insert("options", doc! { "skipEmptyExchange": true });
44+
body.append("options", rawdoc! { "skipEmptyExchange": true });
4345
}
4446

4547
let mut command = Command::new("saslStart", self.source, body);
@@ -75,9 +77,11 @@ impl SaslContinue {
7577
}
7678

7779
pub(super) fn into_command(self) -> Command {
78-
let body = doc! {
80+
// Unwrap safety: the Bson -> RawBson conversion is actually infallible
81+
let raw_id: RawBson = self.conversation_id.try_into().unwrap();
82+
let body = rawdoc! {
7983
"saslContinue": 1,
80-
"conversationId": self.conversation_id,
84+
"conversationId": raw_id,
8185
"payload": Binary { subtype: BinarySubtype::Generic, bytes: self.payload },
8286
};
8387

src/client/auth/scram.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl ClientFirst {
460460
let mut cmd = sasl_start.into_command();
461461

462462
if self.include_db {
463-
cmd.body.insert("db", self.source.clone());
463+
cmd.body.append("db", self.source.clone());
464464
}
465465

466466
cmd

src/client/auth/x509.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use bson::rawdoc;
2+
13
use crate::{
2-
bson::{doc, Document},
4+
bson::Document,
35
client::options::ServerApi,
46
cmap::{Command, Connection, RawCommandResponse},
57
error::{Error, Result},
@@ -16,13 +18,13 @@ pub(crate) fn build_client_first(
1618
credential: &Credential,
1719
server_api: Option<&ServerApi>,
1820
) -> Command {
19-
let mut auth_command_doc = doc! {
21+
let mut auth_command_doc = rawdoc! {
2022
"authenticate": 1,
2123
"mechanism": "MONGODB-X509",
2224
};
2325

2426
if let Some(ref username) = credential.username {
25-
auth_command_doc.insert("username", username);
27+
auth_command_doc.append("username", username.as_str());
2628
}
2729

2830
let mut command = Command::new("authenticate", "$external", auth_command_doc);

src/cmap/conn/command.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,15 @@ use crate::{
1717
#[serde_with::skip_serializing_none]
1818
#[derive(Clone, Debug, Serialize, Default)]
1919
#[serde(rename_all = "camelCase")]
20-
pub(crate) struct Command<T = Document>
21-
where
22-
T: Serialize,
23-
{
20+
pub(crate) struct Command {
2421
#[serde(skip)]
2522
pub(crate) name: String,
2623

2724
#[serde(skip)]
2825
pub(crate) exhaust_allowed: bool,
2926

3027
#[serde(flatten)]
31-
pub(crate) body: T,
28+
pub(crate) body: RawDocumentBuf,
3229

3330
#[serde(skip)]
3431
pub(crate) document_sequences: Vec<DocumentSequence>,
@@ -58,11 +55,8 @@ where
5855
recovery_token: Option<Document>,
5956
}
6057

61-
impl<T> Command<T>
62-
where
63-
T: Serialize,
64-
{
65-
pub(crate) fn new(name: impl ToString, target_db: impl ToString, body: T) -> Self {
58+
impl Command {
59+
pub(crate) fn new(name: impl ToString, target_db: impl ToString, body: RawDocumentBuf) -> Self {
6660
Self {
6761
name: name.to_string(),
6862
target_db: target_db.to_string(),
@@ -85,7 +79,7 @@ where
8579
name: String,
8680
target_db: String,
8781
read_concern: Option<ReadConcern>,
88-
body: T,
82+
body: RawDocumentBuf,
8983
) -> Self {
9084
Self {
9185
name,

src/cmap/conn/wire/message.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::io::Read;
22

33
use bitflags::bitflags;
44
use bson::{doc, Array, Document};
5-
use serde::Serialize;
65
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
76

87
#[cfg(any(
@@ -48,10 +47,7 @@ pub(crate) struct DocumentSequence {
4847
impl Message {
4948
/// Creates a `Message` from a given `Command`. Note that the `response_to` field must be set
5049
/// manually.
51-
pub(crate) fn from_command<T: Serialize>(
52-
command: Command<T>,
53-
request_id: Option<i32>,
54-
) -> Result<Self> {
50+
pub(crate) fn from_command(command: Command, request_id: Option<i32>) -> Result<Self> {
5551
let document_payload = bson::to_raw_document_buf(&command)?;
5652

5753
let mut flags = MessageFlags::empty();

0 commit comments

Comments
 (0)