Skip to content

Commit 6ca8c1d

Browse files
committed
Draft braced structs extension, no tests or special errors yet
1 parent be9e168 commit 6ca8c1d

4 files changed

Lines changed: 112 additions & 34 deletions

File tree

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: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -946,25 +946,28 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
946946
self.start_indent()?;
947947
}
948948

949-
Ok(Compound::new(self, false))
949+
Ok(Compound::new(self, Some(']')))
950950
}
951951

952952
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
953953
let old_newtype_variant = self.newtype_variant;
954954
self.newtype_variant = false;
955955
self.implicit_some_depth = 0;
956956

957-
if !old_newtype_variant {
957+
let closing = if old_newtype_variant {
958+
None
959+
} else {
958960
self.output.write_char('(')?;
959-
}
961+
Some(')')
962+
};
960963

961964
if self.separate_tuple_members() {
962965
self.is_empty = Some(len == 0);
963966

964967
self.start_indent()?;
965968
}
966969

967-
Ok(Compound::new(self, old_newtype_variant))
970+
Ok(Compound::new(self, closing))
968971
}
969972

970973
fn serialize_tuple_struct(
@@ -1001,7 +1004,7 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
10011004
self.start_indent()?;
10021005
}
10031006

1004-
Ok(Compound::new(self, false))
1007+
Ok(Compound::new(self, Some(')')))
10051008
}
10061009

10071010
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
@@ -1018,31 +1021,37 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
10181021
self.start_indent()?;
10191022
}
10201023

1021-
Ok(Compound::new(self, false))
1024+
Ok(Compound::new(self, Some('}')))
10221025
}
10231026

10241027
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
10251028
let old_newtype_variant = self.newtype_variant;
10261029
self.newtype_variant = false;
10271030
self.implicit_some_depth = 0;
10281031

1029-
if old_newtype_variant {
1032+
let closing = if self.extensions().contains(Extensions::BRACED_STRUCTS) {
1033+
self.write_identifier(name)?;
1034+
self.output.write_char('{')?;
1035+
Some('}')
1036+
} else if old_newtype_variant {
10301037
self.validate_identifier(name)?;
1038+
None
10311039
} else {
10321040
if self.struct_names() {
10331041
self.write_identifier(name)?;
10341042
} else {
10351043
self.validate_identifier(name)?;
10361044
}
10371045
self.output.write_char('(')?;
1038-
}
1046+
Some(')')
1047+
};
10391048

10401049
if !self.compact_structs() {
10411050
self.is_empty = Some(len == 0);
10421051
self.start_indent()?;
10431052
}
10441053

1045-
Ok(Compound::new(self, old_newtype_variant))
1054+
Ok(Compound::new(self, closing))
10461055
}
10471056

10481057
fn serialize_struct_variant(
@@ -1057,14 +1066,21 @@ impl<'a, W: fmt::Write> ser::Serializer for &'a mut Serializer<W> {
10571066

10581067
self.validate_identifier(name)?;
10591068
self.write_identifier(variant)?;
1060-
self.output.write_char('(')?;
1069+
1070+
let closing = if self.extensions().contains(Extensions::BRACED_STRUCTS) {
1071+
self.output.write_char('{')?;
1072+
'}'
1073+
} else {
1074+
self.output.write_char('(')?;
1075+
')'
1076+
};
10611077

10621078
if !self.compact_structs() {
10631079
self.is_empty = Some(len == 0);
10641080
self.start_indent()?;
10651081
}
10661082

1067-
Ok(Compound::new(self, false))
1083+
Ok(Compound::new(self, Some(closing)))
10681084
}
10691085
}
10701086

@@ -1077,16 +1093,16 @@ enum State {
10771093
pub struct Compound<'a, W: fmt::Write> {
10781094
ser: &'a mut Serializer<W>,
10791095
state: State,
1080-
newtype_variant: bool,
1096+
closing: Option<char>,
10811097
sequence_index: usize,
10821098
}
10831099

10841100
impl<'a, W: fmt::Write> Compound<'a, W> {
1085-
fn new(ser: &'a mut Serializer<W>, newtype_variant: bool) -> Self {
1101+
fn new(ser: &'a mut Serializer<W>, closing: Option<char>) -> Self {
10861102
Compound {
10871103
ser,
10881104
state: State::First,
1089-
newtype_variant,
1105+
closing,
10901106
sequence_index: 0,
10911107
}
10921108
}
@@ -1151,8 +1167,10 @@ impl<'a, W: fmt::Write> ser::SerializeSeq for Compound<'a, W> {
11511167
self.ser.end_indent()?;
11521168
}
11531169

1154-
// seq always disables `self.newtype_variant`
1155-
self.ser.output.write_char(']')?;
1170+
if let Some(closing) = self.closing {
1171+
self.ser.output.write_char(closing)?;
1172+
}
1173+
11561174
Ok(())
11571175
}
11581176
}
@@ -1200,8 +1218,8 @@ impl<'a, W: fmt::Write> ser::SerializeTuple for Compound<'a, W> {
12001218
self.ser.end_indent()?;
12011219
}
12021220

1203-
if !self.newtype_variant {
1204-
self.ser.output.write_char(')')?;
1221+
if let Some(closing) = self.closing {
1222+
self.ser.output.write_char(closing)?;
12051223
}
12061224

12071225
Ok(())
@@ -1299,8 +1317,10 @@ impl<'a, W: fmt::Write> ser::SerializeMap for Compound<'a, W> {
12991317
self.ser.end_indent()?;
13001318
}
13011319

1302-
// map always disables `self.newtype_variant`
1303-
self.ser.output.write_char('}')?;
1320+
if let Some(closing) = self.closing {
1321+
self.ser.output.write_char(closing)?;
1322+
}
1323+
13041324
Ok(())
13051325
}
13061326
}
@@ -1357,9 +1377,10 @@ impl<'a, W: fmt::Write> ser::SerializeStruct for Compound<'a, W> {
13571377
self.ser.end_indent()?;
13581378
}
13591379

1360-
if !self.newtype_variant {
1361-
self.ser.output.write_char(')')?;
1380+
if let Some(closing) = self.closing {
1381+
self.ser.output.write_char(closing)?;
13621382
}
1383+
13631384
Ok(())
13641385
}
13651386
}

0 commit comments

Comments
 (0)