1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
//! Serialization of internally tagged values.
//!
//! Tagging values internally will embed the tag in the value. As the tag is
//! being embedded in the value, not all types can be supported by this format
//! (see section below).
//!
//! This format is similar to the internally-tagged enum format provided by
//! serde, however allows for various tag types (not only `str` and `u32`).
//!
//! # Warning
//!
//! Deserialization of internally tagged values requires a self-describing
//! data format.
//!
//! Furthermore, neither [`serialize`](serialize) nor the
//! [`Serializer`](Serializer) check for collision of the tag-key with
//! field-names or map-keys of the value with the tag-key. It is up to the
//! caller to make sure that such collisions do not occur.
//!
//! # Supported types
//!
//! Only the following types (of [Serde's data model][datamodel]) are supported
//! by this tagging format:
//!
//! - __seq__
//! * Dynamically sized sequences.
//! * The tag will be the first element of the sequence.
//! - __tuple__
//! * Statically sized sequences.
//! * The tag will be the first element of the tuple.
//! - __map__
//! * Dynamically sized mappings.
//! * The tag-key and tag pair will be added as (first) entry of the mapping:
//! - __struct__
//! * Any normal struct (e.g. `struct Name { ... }`).
//! * The tag will be added as first field under the specified name.
//! - __unit struct__
//! * A struct without content (e.g. `struct Unit;`).
//! * The struct will be serialized as normal struct and the tag will be added
//! as first (and only) field under the specified name.
//! - __newtype struct__ _only if it contains a value that can be serialized
//! with this format_
//! * A tuple struct contianing only a single value (e.g.
//! `struct Newtype(i32)`).
//! * The struct will be serialized as tuple struct and the tag will be added
//! as first element of the tuple.
//! - __tuple struct__
//! * A struct contianing multiple unnamed members (e.g.
//! `struct Tuple(i32, i32)`).
//! * The tag will be added as first element of the tuple.
//! - __internally tagged enum__: any variant
//! * An enum with the `#[serde(tag="<tag-key>")]` attribute.
//! * The tag will be added as first field under the specified name.
//! - __adjacently tagged enum__: any variant
//! * An enum with the `#[serde(tag="<tag-key>", content="<content-key>")]`
//! attribute.
//! * The tag will be added as entry with the specified name as key to the
//! generated mapping.
//! - __untagged enum__: _tuple_, _non-primitive newtype_, and _struct_
//! variants only
//! * An enum with the `#[serde(untagged)]` attribute.
//! * The tag will be embedded using the previously elaborated rules
//! corresponding to the respective variant type.
//!
//! Primitive types and externally tagged enums are not supported.
//!
//! # Examples serializing to JSON
//!
//! ## A Simple struct
//!
//! Serializing a value `foo` with
//!
//! ```
//! # #[macro_use]
//! # extern crate serde_derive;
//! # extern crate serde_json;
//! # extern crate serde_tagged;
//! #
//! #[derive(Serialize)]
//! struct Foo {
//! bar: &'static str,
//! }
//!
//! # fn main() {
//! let foo = Foo { bar: "baz" };
//!
//! let mut serializer = serde_json::Serializer::new(std::io::stdout());
//! serde_tagged::ser::internal::serialize(&mut serializer, "tag-key", "my-tag", &foo).unwrap();
//! # }
//! ```
//!
//! with a tag-value of `"my-tag"` and a tag-field-name of `"tag-key"` will
//! produce the following JSON output:
//!
//! ```json
//! {
//! "tag-key": "my-tag",
//! "bar": "baz"
//! }
//! ```
//!
//!
//! [datamodel]: https://serde.rs/data-model.html
//!
use serde;
use ser::HasDelegate;
/// Embeds a tag into the specified value and then serializes it using the
/// provided serializer.
///
/// Due to the tag being embedded into the value, not all value-types are
/// supported. The specified serializer performs the actual serialization and
/// thus controls the data format. For more information on this trag-format and
/// the supported values, see the [module documentation](::ser::internal).
///
/// This method is a convenience function that creates and uses the
/// [`Serializer`](Serializer) internally.
///
/// # Warning
///
/// This function does not provide any checks regarding collisions of the
/// `tag_key` with field-names or map-keys. The responsibility for such checks
/// reside with the caller.
pub fn serialize<S, T: ?Sized, V: ?Sized>(
serializer: S,
tag_key: &'static str,
tag: &T,
value: &V,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: serde::Serialize,
V: serde::Serialize,
{
value.serialize(Serializer::new(serializer, tag_key, tag))
}
/// A serializer that embeds a tag into to the provided value and then
/// serializes it.
///
/// Due to the tag being embedded into the value, not all value-types are
/// supported. The provided serializer performs the actual serialization and
/// thus controls the data format. For more information on this trag-format and
/// the supported values, see the [module documentation](::ser::internal).
///
/// Due to the tag being embedded into the value, not all value-types are
/// supported. For more details see the [module documentation](::ser::internal).
///
/// # Warning
///
/// This serializer does not provide any checks regarding collisions of the
/// `tag_key` with field-names or map-keys. The responsibility for such checks
/// reside with the caller.
pub struct Serializer<'a, S, T: ?Sized + 'a> {
delegate: S,
tag_key: &'static str,
tag: &'a T,
}
impl<'a, S, T: ?Sized> Serializer<'a, S, T>
where
S: serde::Serializer,
T: serde::Serialize + 'a,
{
/// Creates a new Serializer with the specified tag-key, tag and underlying
/// serializer.
pub fn new(delegate: S, tag_key: &'static str, tag: &'a T) -> Self {
Serializer {
delegate,
tag_key,
tag,
}
}
fn unsupported(&self, what: &'static str) -> S::Error {
serde::ser::Error::custom(format_args!("cannot serialize {} as tagged value", what))
}
}
impl<'a, S, T: ?Sized> HasDelegate for Serializer<'a, S, T>
where
S: serde::Serializer,
T: serde::Serialize,
{
type Ok = S::Ok;
type Error = S::Error;
type Delegate = S;
fn delegate(self) -> S {
self.delegate
}
}
impl<'a, S, T: ?Sized> serde::Serializer for Serializer<'a, S, T>
where
S: serde::Serializer,
T: serde::Serialize + 'a,
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = S::SerializeSeq;
type SerializeTuple = S::SerializeTuple;
type SerializeTupleStruct = S::SerializeTupleStruct;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
type SerializeTupleVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a boolean"))
}
fn serialize_i8(self, _value: i8) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_i16(self, _value: i16) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_i32(self, _value: i32) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_i64(self, _value: i64) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_u8(self, _value: u8) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_u16(self, _value: u16) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_u32(self, _value: u32) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_u64(self, _value: u64) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an integer"))
}
fn serialize_f32(self, _value: f32) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a float"))
}
fn serialize_f64(self, _value: f64) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a float"))
}
fn serialize_char(self, _value: char) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a char"))
}
fn serialize_str(self, _value: &str) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a string"))
}
fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a byte array"))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("an optional"))
}
fn serialize_some<V: ?Sized>(self, _value: &V) -> Result<Self::Ok, Self::Error>
where
V: serde::Serialize,
{
Err(self.unsupported("an optional"))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a unit"))
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(self.unsupported("a unit-variant"))
}
fn serialize_newtype_variant<V: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &V,
) -> Result<Self::Ok, Self::Error>
where
V: serde::Serialize,
{
Err(self.unsupported("a newtype-variant"))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(self.unsupported("a tuple-variant"))
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(self.unsupported("a struct-variant"))
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
use serde::ser::SerializeTuple;
let mut state = self.delegate.serialize_tuple(len + 1)?;
state.serialize_element(self.tag)?;
Ok(state)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
use serde::ser::SerializeSeq;
let mut state = self.delegate.serialize_seq(len.map(|len| len + 1))?;
state.serialize_element(self.tag)?;
Ok(state)
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
use serde::ser::SerializeMap;
let mut state = self.delegate.serialize_map(len.map(|len| len + 1))?;
state.serialize_entry(self.tag_key, self.tag)?;
Ok(state)
}
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
use serde::ser::SerializeStruct;
let mut state = self.delegate.serialize_struct(name, 1)?;
state.serialize_field(self.tag_key, self.tag)?;
state.end()
}
fn serialize_newtype_struct<V: ?Sized>(
self,
_name: &'static str,
value: &V,
) -> Result<Self::Ok, Self::Error>
where
V: serde::Serialize,
{
value.serialize(self)
}
fn serialize_tuple_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
use serde::ser::SerializeTupleStruct;
let mut state = self.delegate.serialize_tuple_struct(name, len + 1)?;
state.serialize_field(self.tag)?;
Ok(state)
}
fn serialize_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
use serde::ser::SerializeStruct;
let mut state = self.delegate.serialize_struct(name, len + 1)?;
state.serialize_field(self.tag_key, self.tag)?;
Ok(state)
}
fn is_human_readable(&self) -> bool {
self.delegate.is_human_readable()
}
}