Skip to content

Commit 0a0672d

Browse files
committed
Draft braced structs extension, no tests or special errors yet
1 parent ea6b406 commit 0a0672d

File tree

4 files changed

+111
-34
lines changed

4 files changed

+111
-34
lines changed

src/de/mod.rs

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,21 @@ impl<'de> Deserializer<'de> {
176176
let old_serde_content_newtype = self.serde_content_newtype;
177177
self.serde_content_newtype = false;
178178

179+
if let Some(ident) = ident {
180+
if is_serde_content {
181+
// serde's Content type uses a singleton map encoding for enums
182+
return visitor.visit_map(SerdeEnumContent {
183+
de: self,
184+
ident: Some(ident),
185+
});
186+
}
187+
188+
if self.extensions().contains(Extensions::BRACED_STRUCTS) {
189+
// giving no name results in worse errors but is necessary here
190+
return self.handle_struct_after_name("", visitor);
191+
}
192+
}
193+
179194
match (
180195
self.parser.check_struct_type(
181196
NewtypeMode::NoParensMeanUnit,
@@ -192,13 +207,6 @@ impl<'de> Deserializer<'de> {
192207
visitor.visit_str(ident)
193208
}
194209
(StructType::Unit, _) => visitor.visit_unit(),
195-
(_, Some(ident)) if is_serde_content => {
196-
// serde's Content type uses a singleton map encoding for enums
197-
visitor.visit_map(SerdeEnumContent {
198-
de: self,
199-
ident: Some(ident),
200-
})
201-
}
202210
(StructType::Named, _) => {
203211
// giving no name results in worse errors but is necessary here
204212
self.handle_struct_after_name("", visitor)
@@ -241,7 +249,38 @@ impl<'de> Deserializer<'de> {
241249
where
242250
V: Visitor<'de>,
243251
{
244-
if self.newtype_variant || self.parser.consume_char('(') {
252+
if self.extensions().contains(Extensions::BRACED_STRUCTS) {
253+
self.newtype_variant = false;
254+
255+
if self.parser.consume_char('{') {
256+
let value = guard_recursion! { self =>
257+
visitor
258+
.visit_map(CommaSeparated::new(Terminator::BracedStruct, self))
259+
.map_err(|err| {
260+
struct_error_name(
261+
err,
262+
if !name_for_pretty_errors_only.is_empty() {
263+
Some(name_for_pretty_errors_only)
264+
} else {
265+
None
266+
},
267+
)
268+
})?
269+
};
270+
271+
self.parser.skip_ws()?;
272+
273+
if self.parser.consume_char('}') {
274+
Ok(value)
275+
} else {
276+
Err(Error::ExpectedStructLikeEnd)
277+
}
278+
} else if name_for_pretty_errors_only.is_empty() {
279+
Err(Error::ExpectedStructLike)
280+
} else {
281+
Err(Error::ExpectedNamedStructLike(name_for_pretty_errors_only))
282+
}
283+
} else if self.newtype_variant || self.parser.consume_char('(') {
245284
let old_newtype_variant = self.newtype_variant;
246285
self.newtype_variant = false;
247286

@@ -719,6 +758,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
719758
where
720759
V: Visitor<'de>,
721760
{
761+
if self.extensions().contains(Extensions::BRACED_STRUCTS) {
762+
self.newtype_variant = false;
763+
}
764+
722765
if !self.newtype_variant {
723766
self.parser.consume_struct_name(name)?;
724767
}
@@ -778,13 +821,14 @@ enum Terminator {
778821
MapAsStruct,
779822
Tuple,
780823
Struct,
824+
BracedStruct,
781825
Seq,
782826
}
783827

784828
impl Terminator {
785829
fn as_char(&self) -> char {
786830
match self {
787-
Terminator::Map | Terminator::MapAsStruct => '}',
831+
Terminator::Map | Terminator::MapAsStruct | Terminator::BracedStruct => '}',
788832
Terminator::Tuple | Terminator::Struct => ')',
789833
Terminator::Seq => ']',
790834
}
@@ -856,7 +900,7 @@ impl<'de, 'a> de::MapAccess<'de> for CommaSeparated<'a, 'de> {
856900
std::any::type_name::<K::Value>() == SERDE_TAG_KEY_CANARY;
857901

858902
match self.terminator {
859-
Terminator::Struct => guard_recursion! { self.de =>
903+
Terminator::Struct | Terminator::BracedStruct => guard_recursion! { self.de =>
860904
seed.deserialize(&mut id::Deserializer::new(&mut *self.de, false)).map(Some)
861905
},
862906
Terminator::MapAsStruct => guard_recursion! { self.de =>

src/extensions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ bitflags::bitflags! {
1111
///
1212
/// During deserialization, this extension requires that structs' names are stated explicitly.
1313
const EXPLICIT_STRUCT_NAMES = 0x8;
14+
const BRACED_STRUCTS = 0x10;
1415
}
1516
}
1617
// GRCOV_EXCL_STOP

src/parse.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,17 @@ impl<'a> Parser<'a> {
572572

573573
match parser.peek_char() {
574574
// Definitely a struct with named fields
575-
Some(':') => return Ok(StructType::Named),
575+
Some(':') => {
576+
if parser.exts.contains(Extensions::BRACED_STRUCTS) {
577+
return Err(Error::ExpectedStructLike);
578+
} else {
579+
return Ok(StructType::Named);
580+
}
581+
}
582+
// Definitely a braced struct with named fields
583+
Some('{') if parser.exts.contains(Extensions::BRACED_STRUCTS) => {
584+
return Ok(StructType::Named)
585+
}
576586
// Definitely a tuple-like struct with fields
577587
Some(',') => {
578588
parser.skip_next_char();
@@ -668,7 +678,9 @@ impl<'a> Parser<'a> {
668678

669679
pub fn consume_struct_name(&mut self, ident: &'static str) -> Result<bool> {
670680
if self.check_ident("") {
671-
if self.exts.contains(Extensions::EXPLICIT_STRUCT_NAMES) {
681+
if self.exts.contains(Extensions::EXPLICIT_STRUCT_NAMES)
682+
|| self.exts.contains(Extensions::BRACED_STRUCTS)
683+
{
672684
return Err(Error::ExpectedStructName(ident.to_string()));
673685
}
674686

src/ser/mod.rs

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -956,25 +956,28 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
956956
self.start_indent()?;
957957
}
958958

959-
Ok(Compound::new(self, false))
959+
Ok(Compound::new(self, Some(']')))
960960
}
961961

962962
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
963963
let old_newtype_variant = self.newtype_variant;
964964
self.newtype_variant = false;
965965
self.implicit_some_depth = 0;
966966

967-
if !old_newtype_variant {
967+
let closing = if old_newtype_variant {
968+
None
969+
} else {
968970
self.output.write_char('(')?;
969-
}
971+
Some(')')
972+
};
970973

971974
if self.separate_tuple_members() {
972975
self.is_empty = Some(len == 0);
973976

974977
self.start_indent()?;
975978
}
976979

977-
Ok(Compound::new(self, old_newtype_variant))
980+
Ok(Compound::new(self, closing))
978981
}
979982

980983
fn serialize_tuple_struct(
@@ -1011,7 +1014,7 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
10111014
self.start_indent()?;
10121015
}
10131016

1014-
Ok(Compound::new(self, false))
1017+
Ok(Compound::new(self, Some(')')))
10151018
}
10161019

10171020
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
@@ -1028,31 +1031,37 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
10281031
self.start_indent()?;
10291032
}
10301033

1031-
Ok(Compound::new(self, false))
1034+
Ok(Compound::new(self, Some('}')))
10321035
}
10331036

10341037
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
10351038
let old_newtype_variant = self.newtype_variant;
10361039
self.newtype_variant = false;
10371040
self.implicit_some_depth = 0;
10381041

1039-
if old_newtype_variant {
1042+
let closing = if self.extensions().contains(Extensions::BRACED_STRUCTS) {
1043+
self.write_identifier(name)?;
1044+
self.output.write_char('{')?;
1045+
Some('}')
1046+
} else if old_newtype_variant {
10401047
self.validate_identifier(name)?;
1048+
None
10411049
} else {
10421050
if self.struct_names() {
10431051
self.write_identifier(name)?;
10441052
} else {
10451053
self.validate_identifier(name)?;
10461054
}
10471055
self.output.write_char('(')?;
1048-
}
1056+
Some(')')
1057+
};
10491058

10501059
if !self.compact_structs() {
10511060
self.is_empty = Some(len == 0);
10521061
self.start_indent()?;
10531062
}
10541063

1055-
Ok(Compound::new(self, old_newtype_variant))
1064+
Ok(Compound::new(self, closing))
10561065
}
10571066

10581067
fn serialize_struct_variant(
@@ -1067,14 +1076,21 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
10671076

10681077
self.validate_identifier(name)?;
10691078
self.write_identifier(variant)?;
1070-
self.output.write_char('(')?;
1079+
1080+
let closing = if self.extensions().contains(Extensions::BRACED_STRUCTS) {
1081+
self.output.write_char('{')?;
1082+
'}'
1083+
} else {
1084+
self.output.write_char('(')?;
1085+
')'
1086+
};
10711087

10721088
if !self.compact_structs() {
10731089
self.is_empty = Some(len == 0);
10741090
self.start_indent()?;
10751091
}
10761092

1077-
Ok(Compound::new(self, false))
1093+
Ok(Compound::new(self, Some(closing)))
10781094
}
10791095
}
10801096

@@ -1087,16 +1103,16 @@ enum State {
10871103
pub struct Compound<'a, W: fmt::Write> {
10881104
ser: &'a mut Serializer<W>,
10891105
state: State,
1090-
newtype_variant: bool,
1106+
closing: Option<char>,
10911107
sequence_index: usize,
10921108
}
10931109

10941110
impl<'a, W: fmt::Write> Compound<'a, W> {
1095-
fn new(ser: &'a mut Serializer<W>, newtype_variant: bool) -> Self {
1111+
fn new(ser: &'a mut Serializer<W>, closing: Option<char>) -> Self {
10961112
Compound {
10971113
ser,
10981114
state: State::First,
1099-
newtype_variant,
1115+
closing,
11001116
sequence_index: 0,
11011117
}
11021118
}
@@ -1161,8 +1177,10 @@ impl<'a, W: fmt::Write> ser::SerializeSeq for Compound<'a, W> {
11611177
self.ser.end_indent()?;
11621178
}
11631179

1164-
// seq always disables `self.newtype_variant`
1165-
self.ser.output.write_char(']')?;
1180+
if let Some(closing) = self.closing {
1181+
self.ser.output.write_char(closing)?;
1182+
}
1183+
11661184
Ok(())
11671185
}
11681186
}
@@ -1210,8 +1228,8 @@ impl<'a, W: fmt::Write> ser::SerializeTuple for Compound<'a, W> {
12101228
self.ser.end_indent()?;
12111229
}
12121230

1213-
if !self.newtype_variant {
1214-
self.ser.output.write_char(')')?;
1231+
if let Some(closing) = self.closing {
1232+
self.ser.output.write_char(closing)?;
12151233
}
12161234

12171235
Ok(())
@@ -1309,8 +1327,10 @@ impl<'a, W: fmt::Write> ser::SerializeMap for Compound<'a, W> {
13091327
self.ser.end_indent()?;
13101328
}
13111329

1312-
// map always disables `self.newtype_variant`
1313-
self.ser.output.write_char('}')?;
1330+
if let Some(closing) = self.closing {
1331+
self.ser.output.write_char(closing)?;
1332+
}
1333+
13141334
Ok(())
13151335
}
13161336
}
@@ -1399,8 +1419,8 @@ impl<'a, W: fmt::Write> ser::SerializeStruct for Compound<'a, W> {
13991419
self.ser.end_indent()?;
14001420
}
14011421

1402-
if !self.newtype_variant {
1403-
self.ser.output.write_char(')')?;
1422+
if let Some(closing) = self.closing {
1423+
self.ser.output.write_char(closing)?;
14041424
}
14051425

14061426
Ok(())

0 commit comments

Comments
 (0)