Skip to content

Commit d32ccc1

Browse files
committed
serde conversion
1 parent 718073e commit d32ccc1

File tree

15 files changed

+99
-48
lines changed

15 files changed

+99
-48
lines changed

src/bson.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ impl From<String> for Bson {
268268
}
269269
}
270270

271+
impl From<crate::raw::CString> for Bson {
272+
fn from(a: crate::raw::CString) -> Bson {
273+
Bson::String(a.into_string())
274+
}
275+
}
276+
271277
impl From<Document> for Bson {
272278
fn from(a: Document) -> Bson {
273279
Bson::Document(a)
@@ -619,7 +625,7 @@ impl Bson {
619625
ref pattern,
620626
ref options,
621627
}) => {
622-
let mut chars: Vec<_> = options.chars().collect();
628+
let mut chars: Vec<_> = options.as_str().chars().collect();
623629
chars.sort_unstable();
624630

625631
let options: String = chars.into_iter().collect();
@@ -842,7 +848,9 @@ impl Bson {
842848
if let Ok(regex) = doc.get_document("$regularExpression") {
843849
if let Ok(pattern) = regex.get_str("pattern") {
844850
if let Ok(options) = regex.get_str("options") {
845-
return Bson::RegularExpression(Regex::new(pattern, options));
851+
if let Ok(regex) = Regex::new(pattern, options) {
852+
return Bson::RegularExpression(regex);
853+
}
846854
}
847855
}
848856
}
@@ -1160,7 +1168,6 @@ pub struct Regex {
11601168
}
11611169

11621170
impl Regex {
1163-
#[cfg(test)]
11641171
pub(crate) fn new(
11651172
pattern: impl AsRef<str>,
11661173
options: impl AsRef<str>,

src/de/raw.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,15 +1306,15 @@ impl<'de> serde::de::Deserializer<'de> for &mut RegexAccess<'de> {
13061306
RegexDeserializationStage::Pattern => {
13071307
self.stage = RegexDeserializationStage::Options;
13081308
match &self.re {
1309-
BsonCow::Borrowed(re) => visitor.visit_borrowed_str(re.pattern),
1310-
BsonCow::Owned(re) => visitor.visit_str(&re.pattern),
1309+
BsonCow::Borrowed(re) => visitor.visit_borrowed_str(re.pattern.as_str()),
1310+
BsonCow::Owned(re) => visitor.visit_str(&re.pattern.as_str()),
13111311
}
13121312
}
13131313
RegexDeserializationStage::Options => {
13141314
self.stage = RegexDeserializationStage::Done;
13151315
match &self.re {
1316-
BsonCow::Borrowed(re) => visitor.visit_borrowed_str(re.options),
1317-
BsonCow::Owned(re) => visitor.visit_str(&re.options),
1316+
BsonCow::Borrowed(re) => visitor.visit_borrowed_str(re.options.as_str()),
1317+
BsonCow::Owned(re) => visitor.visit_str(&re.options.as_str()),
13181318
}
13191319
}
13201320
RegexDeserializationStage::Done => {

src/de/serde.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,9 @@ impl<'de> Visitor<'de> for BsonVisitor {
442442

443443
"$regularExpression" => {
444444
let re = visitor.next_value::<extjson::models::RegexBody>()?;
445-
return Ok(Bson::RegularExpression(Regex::new(re.pattern, re.options)));
445+
return Ok(Bson::RegularExpression(
446+
Regex::new(re.pattern, re.options).map_err(serde::de::Error::custom)?,
447+
));
446448
}
447449

448450
"$dbPointer" => {

src/extjson/de.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl TryFrom<serde_json::Map<String, serde_json::Value>> for Bson {
5555

5656
if obj.contains_key("$regularExpression") {
5757
let regex: models::Regex = serde_json::from_value(obj.into())?;
58-
return Ok(regex.parse().into());
58+
return Ok(regex.parse()?.into());
5959
}
6060

6161
if obj.contains_key("$numberInt") {

src/extjson/models.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ pub(crate) struct RegexBody {
122122
}
123123

124124
impl Regex {
125-
pub(crate) fn parse(self) -> crate::Regex {
125+
pub(crate) fn parse(self) -> crate::error::Result<crate::Regex> {
126126
crate::Regex::new(self.body.pattern, self.body.options)
127127
}
128128
}

src/raw/bson_ref.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,15 @@ impl<'a> RawBsonRef<'a> {
255255
RawBsonRef::Document(d) => RawBson::Document(d.to_owned()),
256256
RawBsonRef::Boolean(b) => RawBson::Boolean(b),
257257
RawBsonRef::Null => RawBson::Null,
258-
RawBsonRef::RegularExpression(re) => RawBson::RegularExpression(Regex {
259-
pattern: re.pattern.into(),
260-
options: re.options.into(),
261-
}),
258+
RawBsonRef::RegularExpression(re) => {
259+
let mut chars: Vec<_> = re.options.as_str().chars().collect();
260+
chars.sort_unstable();
261+
let options: String = chars.into_iter().collect();
262+
RawBson::RegularExpression(Regex {
263+
pattern: re.pattern.into(),
264+
options: super::CString::from_unchecked(options),
265+
})
266+
}
262267
RawBsonRef::JavaScriptCode(c) => RawBson::JavaScriptCode(c.to_owned()),
263268
RawBsonRef::JavaScriptCodeWithScope(c_w_s) => {
264269
RawBson::JavaScriptCodeWithScope(RawJavaScriptCodeWithScope {
@@ -629,8 +634,8 @@ impl serde::Serialize for RawRegexRef<'_> {
629634
{
630635
#[derive(serde::Serialize)]
631636
struct BorrowedRegexBody<'a> {
632-
pattern: &'a str,
633-
options: &'a str,
637+
pattern: &'a CStr,
638+
options: &'a CStr,
634639
}
635640

636641
let mut state = serializer.serialize_struct("$regularExpression", 1)?;

src/raw/cstr.rs

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,29 @@ impl<'a, 'b> PartialEq<&'b CStr> for &'a CStr {
5151
}
5252
}
5353

54+
impl std::borrow::ToOwned for CStr {
55+
type Owned = CString;
56+
57+
fn to_owned(&self) -> Self::Owned {
58+
self.into()
59+
}
60+
}
61+
62+
#[cfg(feature = "serde")]
63+
impl serde::Serialize for &CStr {
64+
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
65+
where
66+
S: serde::Serializer,
67+
{
68+
self.as_str().serialize(serializer)
69+
}
70+
}
71+
5472
#[diagnostic::on_unimplemented(message = "the string literal contains a zero byte")]
5573
pub trait ValidCStr {}
5674
pub struct IsValidCStr<const VALID: bool>;
5775
impl ValidCStr for IsValidCStr<true> {}
5876

59-
#[derive(Clone, Eq, PartialEq, Hash)]
60-
#[repr(transparent)]
61-
pub struct CString {
62-
data: String,
63-
}
64-
6577
pub const fn validate_cstr(text: &str) -> Option<&CStr> {
6678
let bytes = text.as_bytes();
6779
let mut i = 0;
@@ -86,6 +98,12 @@ macro_rules! cstr {
8698
}
8799
pub use cstr;
88100

101+
#[derive(Clone, Eq, PartialEq, Hash)]
102+
#[repr(transparent)]
103+
pub struct CString {
104+
data: String,
105+
}
106+
89107
impl TryFrom<String> for CString {
90108
type Error = Error;
91109

@@ -95,7 +113,20 @@ impl TryFrom<String> for CString {
95113
}
96114
}
97115

116+
impl TryFrom<&str> for CString {
117+
type Error = Error;
118+
119+
fn try_from(data: &str) -> Result<Self> {
120+
let cs: &CStr = data.try_into()?;
121+
Ok(cs.into())
122+
}
123+
}
124+
98125
impl CString {
126+
pub(crate) fn from_unchecked(data: String) -> Self {
127+
Self { data }
128+
}
129+
99130
pub fn into_string(self) -> String {
100131
self.data
101132
}
@@ -130,3 +161,9 @@ impl std::fmt::Display for CString {
130161
self.data.fmt(f)
131162
}
132163
}
164+
165+
impl std::borrow::Borrow<CStr> for CString {
166+
fn borrow(&self) -> &CStr {
167+
self.as_ref()
168+
}
169+
}

src/raw/iter.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,11 @@ impl TryInto<Bson> for RawElement<'_> {
145145
impl<'a> RawElement<'a> {
146146
#[cfg(feature = "serde")]
147147
pub(crate) fn toplevel(bytes: &'a [u8]) -> Result<Self> {
148+
use crate::raw::cstr;
149+
148150
let doc = RawDocument::decode_from_bytes(bytes)?;
149151
Ok(Self {
150-
key: "TOPLEVEL",
152+
key: cstr!("TOPLEVEL"),
151153
kind: ElementType::EmbeddedDocument,
152154
doc,
153155
start_at: 0,

src/raw/serde/bson_visitor.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ impl OwnedOrBorrowedRawBsonVisitor {
8484
match (body.pattern, body.options) {
8585
(Cow::Borrowed(p), Cow::Borrowed(o)) => {
8686
RawBsonRef::RegularExpression(RawRegexRef {
87-
pattern: p,
88-
options: o,
87+
pattern: p.try_into().map_err(A::Error::custom)?,
88+
options: o.try_into().map_err(A::Error::custom)?,
8989
})
9090
.into()
9191
}
9292
(p, o) => RawBson::RegularExpression(Regex {
93-
pattern: p.into_owned(),
94-
options: o.into_owned(),
93+
pattern: p.into_owned().try_into().map_err(A::Error::custom)?,
94+
options: o.into_owned().try_into().map_err(A::Error::custom)?,
9595
})
9696
.into(),
9797
}

src/ser/raw/value_serializer.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ enum SerializationStep {
5151
RegEx,
5252
RegExPattern,
5353
RegExOptions {
54-
pattern: String,
54+
pattern: crate::raw::CString,
5555
},
5656

5757
Timestamp,
@@ -289,16 +289,19 @@ impl<'b> serde::Serializer for &'b mut ValueSerializer<'_> {
289289
}
290290
SerializationStep::RegExPattern => {
291291
self.state = SerializationStep::RegExOptions {
292-
pattern: v.to_string(),
292+
pattern: v.to_string().try_into()?,
293293
};
294294
}
295295
SerializationStep::RegExOptions { pattern } => {
296296
let mut chars: Vec<_> = v.chars().collect();
297297
chars.sort_unstable();
298298

299-
let options = &chars.into_iter().collect::<String>();
300-
RawBsonRef::RegularExpression(crate::RawRegexRef { pattern, options })
301-
.append_to(&mut self.root_serializer.bytes)?;
299+
let options = chars.into_iter().collect::<String>();
300+
RawBsonRef::RegularExpression(crate::RawRegexRef {
301+
pattern: pattern.as_ref(),
302+
options: options.as_str().try_into()?,
303+
})
304+
.append_to(&mut self.root_serializer.bytes)?;
302305
}
303306
SerializationStep::Code => {
304307
RawBsonRef::JavaScriptCode(v).append_to(&mut self.root_serializer.bytes)?;

0 commit comments

Comments
 (0)