Skip to content

Commit fba9629

Browse files
committed
Correctly serialize enum variants renamed to $text
Follow-up for tafia#541
1 parent 4b298fd commit fba9629

File tree

4 files changed

+191
-19
lines changed

4 files changed

+191
-19
lines changed

Changelog.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
### New Features
1414

15-
- [#541]: Deserialize specially named `$text` enum variant in [externally tagged]
16-
enums from textual content
15+
- [#541]: (De)serialize specially named `$text` enum variant in [externally tagged]
16+
enums to / from textual content
1717
- [#556]: `to_writer` and `to_string` now accept `?Sized` types
1818
- [#556]: Add new `to_writer_with_root` and `to_string_with_root` helper functions
1919
- [#520]: Add methods `BytesText::inplace_trim_start` and `BytesText::inplace_trim_end`

src/se/content.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Contains serializer for content of an XML element
22
33
use crate::errors::serialize::DeError;
4-
use crate::se::element::{ElementSerializer, Struct};
4+
use crate::se::element::{ElementSerializer, Struct, Tuple};
55
use crate::se::simple_type::{QuoteTarget, SimpleTypeSerializer};
66
use crate::se::{Indent, QuoteLevel, XmlName};
77
use serde::ser::{
@@ -132,7 +132,7 @@ impl<'w, 'i, W: Write> Serializer for ContentSerializer<'w, 'i, W> {
132132
type SerializeSeq = Self;
133133
type SerializeTuple = Self;
134134
type SerializeTupleStruct = Self;
135-
type SerializeTupleVariant = ElementSerializer<'w, 'i, W>;
135+
type SerializeTupleVariant = Tuple<'w, 'i, W>;
136136
type SerializeMap = Impossible<Self::Ok, Self::Error>;
137137
type SerializeStruct = Impossible<Self::Ok, Self::Error>;
138138
type SerializeStructVariant = Struct<'w, 'i, W>;
@@ -258,7 +258,7 @@ impl<'w, 'i, W: Write> Serializer for ContentSerializer<'w, 'i, W> {
258258
// `ElementSerializer::serialize_tuple_variant` is the same as
259259
// `ElementSerializer::serialize_tuple_struct`, except that it replaces `.key`
260260
// to `variant` which is not required here
261-
ser.serialize_tuple_struct(name, len)
261+
ser.serialize_tuple_struct(name, len).map(Tuple::Element)
262262
}
263263

264264
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {

src/se/element.rs

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::de::{TEXT_KEY, VALUE_KEY};
44
use crate::errors::serialize::DeError;
55
use crate::se::content::ContentSerializer;
66
use crate::se::key::QNameSerializer;
7-
use crate::se::simple_type::{QuoteTarget, SimpleTypeSerializer};
7+
use crate::se::simple_type::{QuoteTarget, SimpleSeq, SimpleTypeSerializer};
88
use crate::se::{Indent, XmlName};
99
use serde::ser::{
1010
Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
@@ -37,7 +37,7 @@ impl<'w, 'k, W: Write> Serializer for ElementSerializer<'w, 'k, W> {
3737
type SerializeSeq = Self;
3838
type SerializeTuple = Self;
3939
type SerializeTupleStruct = Self;
40-
type SerializeTupleVariant = Self;
40+
type SerializeTupleVariant = Tuple<'w, 'k, W>;
4141
type SerializeMap = Map<'w, 'k, W>;
4242
type SerializeStruct = Struct<'w, 'k, W>;
4343
type SerializeStructVariant = Struct<'w, 'k, W>;
@@ -105,12 +105,19 @@ impl<'w, 'k, W: Write> Serializer for ElementSerializer<'w, 'k, W> {
105105

106106
fn serialize_unit_variant(
107107
self,
108-
_name: &'static str,
108+
name: &'static str,
109109
_variant_index: u32,
110110
variant: &'static str,
111111
) -> Result<Self::Ok, Self::Error> {
112-
let name = XmlName::try_from(variant)?;
113-
self.ser.write_empty(name)
112+
if variant == TEXT_KEY {
113+
// We should write some text but we don't known what text to write
114+
Err(DeError::Unsupported(
115+
format!("`{}::$text` unit variant cannot be serialized", name).into(),
116+
))
117+
} else {
118+
let name = XmlName::try_from(variant)?;
119+
self.ser.write_empty(name)
120+
}
114121
}
115122

116123
fn serialize_newtype_struct<T: ?Sized + Serialize>(
@@ -128,8 +135,13 @@ impl<'w, 'k, W: Write> Serializer for ElementSerializer<'w, 'k, W> {
128135
variant: &'static str,
129136
value: &T,
130137
) -> Result<Self::Ok, Self::Error> {
131-
self.key = XmlName::try_from(variant)?;
132-
value.serialize(self)
138+
if variant == TEXT_KEY {
139+
value.serialize(self.ser.into_simple_type_serializer())?;
140+
Ok(())
141+
} else {
142+
self.key = XmlName::try_from(variant)?;
143+
value.serialize(self)
144+
}
133145
}
134146

135147
#[inline]
@@ -159,8 +171,15 @@ impl<'w, 'k, W: Write> Serializer for ElementSerializer<'w, 'k, W> {
159171
variant: &'static str,
160172
len: usize,
161173
) -> Result<Self::SerializeTupleVariant, Self::Error> {
162-
self.key = XmlName::try_from(variant)?;
163-
self.serialize_tuple_struct(name, len)
174+
if variant == TEXT_KEY {
175+
self.ser
176+
.into_simple_type_serializer()
177+
.serialize_tuple_struct(name, len)
178+
.map(Tuple::Text)
179+
} else {
180+
self.key = XmlName::try_from(variant)?;
181+
self.serialize_tuple_struct(name, len).map(Tuple::Element)
182+
}
164183
}
165184

166185
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -195,8 +214,14 @@ impl<'w, 'k, W: Write> Serializer for ElementSerializer<'w, 'k, W> {
195214
variant: &'static str,
196215
len: usize,
197216
) -> Result<Self::SerializeStructVariant, Self::Error> {
198-
self.key = XmlName::try_from(variant)?;
199-
self.serialize_struct(name, len)
217+
if variant == TEXT_KEY {
218+
Err(DeError::Unsupported(
219+
format!("`{}::$text` struct variant cannot be serialized", name).into(),
220+
))
221+
} else {
222+
self.key = XmlName::try_from(variant)?;
223+
self.serialize_struct(name, len)
224+
}
200225
}
201226
}
202227

@@ -259,7 +284,19 @@ impl<'w, 'k, W: Write> SerializeTupleStruct for ElementSerializer<'w, 'k, W> {
259284
}
260285
}
261286

262-
impl<'w, 'k, W: Write> SerializeTupleVariant for ElementSerializer<'w, 'k, W> {
287+
////////////////////////////////////////////////////////////////////////////////////////////////////
288+
289+
/// A serializer for tuple variants. Tuples can be serialized in two modes:
290+
/// - wrapping each tuple field into a tag
291+
/// - without wrapping, fields are delimited by a space
292+
pub enum Tuple<'w, 'k, W: Write> {
293+
/// Serialize each tuple field as an element
294+
Element(ElementSerializer<'w, 'k, W>),
295+
/// Serialize tuple as an `xs:list`: space-delimited content of fields
296+
Text(SimpleSeq<'k, &'w mut W>),
297+
}
298+
299+
impl<'w, 'k, W: Write> SerializeTupleVariant for Tuple<'w, 'k, W> {
263300
type Ok = ();
264301
type Error = DeError;
265302

@@ -268,12 +305,18 @@ impl<'w, 'k, W: Write> SerializeTupleVariant for ElementSerializer<'w, 'k, W> {
268305
where
269306
T: ?Sized + Serialize,
270307
{
271-
<Self as SerializeTuple>::serialize_element(self, value)
308+
match self {
309+
Tuple::Element(ser) => SerializeTuple::serialize_element(ser, value),
310+
Tuple::Text(ser) => SerializeTuple::serialize_element(ser, value),
311+
}
272312
}
273313

274314
#[inline]
275315
fn end(self) -> Result<Self::Ok, Self::Error> {
276-
<Self as SerializeTuple>::end(self)
316+
match self {
317+
Tuple::Element(ser) => SerializeTuple::end(ser),
318+
Tuple::Text(ser) => SerializeTuple::end(ser).map(|_| ()),
319+
}
277320
}
278321
}
279322

tests/serde-se.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,49 @@ mod without_root {
351351
42\
352352
<string>answer</string>\
353353
</Text>");
354+
355+
/// Test serialization of the specially named variant `$text`
356+
mod text {
357+
use super::*;
358+
use pretty_assertions::assert_eq;
359+
360+
#[derive(Serialize)]
361+
enum Unit {
362+
#[serde(rename = "$text")]
363+
Text,
364+
}
365+
#[derive(Serialize)]
366+
enum Newtype<'a> {
367+
#[serde(rename = "$text")]
368+
Text(&'a str),
369+
}
370+
#[derive(Serialize)]
371+
enum Tuple<'a> {
372+
#[serde(rename = "$text")]
373+
Text(f64, &'a str),
374+
}
375+
#[derive(Serialize)]
376+
enum Struct<'a> {
377+
#[serde(rename = "$text")]
378+
Text { float: f64, string: &'a str },
379+
}
380+
381+
// It is unknown how to exactly serialize unit to a text
382+
err!(unit: Unit::Text => Unsupported("`Unit::$text` unit variant cannot be serialized"));
383+
serialize_as!(newtype: Newtype::Text("newtype text") => "newtype text");
384+
// Tuple variant serialized as an `xs:list`
385+
serialize_as!(tuple: Tuple::Text(4.2, "newtype text") => "4.2 newtype&#32;text");
386+
// Struct variant cannot be directly serialized to a text
387+
err!(struct_:
388+
Struct::Text {
389+
float: 4.2,
390+
string: "newtype text",
391+
}
392+
=> Unsupported("`Struct::$text` struct variant cannot be serialized"));
393+
}
354394
}
355395

396+
/// Name `$text` has no special meaning in internally tagged enums
356397
mod internally_tagged {
357398
use super::*;
358399
use pretty_assertions::assert_eq;
@@ -417,6 +458,7 @@ mod without_root {
417458
</InternallyTagged>");
418459
}
419460

461+
/// Name `$text` has no special meaning in adjacently tagged enums
420462
mod adjacently_tagged {
421463
use super::*;
422464
use pretty_assertions::assert_eq;
@@ -497,6 +539,7 @@ mod without_root {
497539
</AdjacentlyTagged>");
498540
}
499541

542+
/// Name `$text` has no special meaning in untagged enums
500543
mod untagged {
501544
use super::*;
502545
use pretty_assertions::assert_eq;
@@ -745,8 +788,49 @@ mod without_root {
745788
42\n \
746789
<string>answer</string>\n\
747790
</Text>");
791+
792+
/// Test serialization of the specially named variant `$text`
793+
mod text {
794+
use super::*;
795+
use pretty_assertions::assert_eq;
796+
797+
#[derive(Serialize)]
798+
enum Unit {
799+
#[serde(rename = "$text")]
800+
Text,
801+
}
802+
#[derive(Serialize)]
803+
enum Newtype<'a> {
804+
#[serde(rename = "$text")]
805+
Text(&'a str),
806+
}
807+
#[derive(Serialize)]
808+
enum Tuple<'a> {
809+
#[serde(rename = "$text")]
810+
Text(f64, &'a str),
811+
}
812+
#[derive(Serialize)]
813+
enum Struct<'a> {
814+
#[serde(rename = "$text")]
815+
Text { float: f64, string: &'a str },
816+
}
817+
818+
// It is unknown how to exactly serialize unit to a text
819+
err!(unit: Unit::Text => Unsupported("`Unit::$text` unit variant cannot be serialized"));
820+
serialize_as!(newtype: Newtype::Text("newtype text") => "newtype text");
821+
// Tuple variant serialized as an `xs:list`
822+
serialize_as!(tuple: Tuple::Text(4.2, "newtype text") => "4.2 newtype&#32;text");
823+
// Struct variant cannot be directly serialized to a text
824+
err!(struct_:
825+
Struct::Text {
826+
float: 4.2,
827+
string: "newtype text",
828+
}
829+
=> Unsupported("`Struct::$text` struct variant cannot be serialized"));
830+
}
748831
}
749832

833+
/// Name `$text` has no special meaning in untagged enums
750834
mod internally_tagged {
751835
use super::*;
752836
use pretty_assertions::assert_eq;
@@ -811,6 +895,7 @@ mod without_root {
811895
</InternallyTagged>");
812896
}
813897

898+
/// Name `$text` has no special meaning in untagged enums
814899
mod adjacently_tagged {
815900
use super::*;
816901
use pretty_assertions::assert_eq;
@@ -891,6 +976,7 @@ mod without_root {
891976
</AdjacentlyTagged>");
892977
}
893978

979+
/// Name `$text` has no special meaning in untagged enums
894980
mod untagged {
895981
use super::*;
896982
use pretty_assertions::assert_eq;
@@ -1156,8 +1242,49 @@ mod with_root {
11561242
42\
11571243
<string>answer</string>\
11581244
</Text>");
1245+
1246+
/// Test serialization of the specially named variant `$text`
1247+
mod text {
1248+
use super::*;
1249+
use pretty_assertions::assert_eq;
1250+
1251+
#[derive(Serialize)]
1252+
enum Unit {
1253+
#[serde(rename = "$text")]
1254+
Text,
1255+
}
1256+
#[derive(Serialize)]
1257+
enum Newtype<'a> {
1258+
#[serde(rename = "$text")]
1259+
Text(&'a str),
1260+
}
1261+
#[derive(Serialize)]
1262+
enum Tuple<'a> {
1263+
#[serde(rename = "$text")]
1264+
Text(f64, &'a str),
1265+
}
1266+
#[derive(Serialize)]
1267+
enum Struct<'a> {
1268+
#[serde(rename = "$text")]
1269+
Text { float: f64, string: &'a str },
1270+
}
1271+
1272+
// It is unknown how to exactly serialize unit to a text
1273+
err!(unit: Unit::Text => Unsupported("`Unit::$text` unit variant cannot be serialized"));
1274+
serialize_as!(newtype: Newtype::Text("newtype text") => "newtype text");
1275+
// Tuple variant serialized as an `xs:list`
1276+
serialize_as!(tuple: Tuple::Text(4.2, "newtype text") => "4.2 newtype&#32;text");
1277+
// Struct variant cannot be directly serialized to a text
1278+
err!(struct_:
1279+
Struct::Text {
1280+
float: 4.2,
1281+
string: "newtype text",
1282+
}
1283+
=> Unsupported("`Struct::$text` struct variant cannot be serialized"));
1284+
}
11591285
}
11601286

1287+
/// Name `$text` has no special meaning in adjacently tagged enums
11611288
mod internally_tagged {
11621289
use super::*;
11631290
use pretty_assertions::assert_eq;
@@ -1222,6 +1349,7 @@ mod with_root {
12221349
</root>");
12231350
}
12241351

1352+
/// Name `$text` has no special meaning in adjacently tagged enums
12251353
mod adjacently_tagged {
12261354
use super::*;
12271355
use pretty_assertions::assert_eq;
@@ -1302,6 +1430,7 @@ mod with_root {
13021430
</root>");
13031431
}
13041432

1433+
/// Name `$text` has no special meaning in untagged enums
13051434
mod untagged {
13061435
use super::*;
13071436
use pretty_assertions::assert_eq;

0 commit comments

Comments
 (0)