diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index b29ef65..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: CI - -on: - push: - pull_request: - workflow_dispatch: - schedule: [cron: "40 1 * * *"] - -permissions: - contents: read - -env: - RUSTFLAGS: -Dwarnings - -jobs: - test: - name: Rust ${{matrix.rust}} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - rust: [nightly, beta, stable, 1.56.0] - timeout-minutes: 45 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{matrix.rust}} - - run: cargo test - - uses: actions/upload-artifact@v4 - if: matrix.rust == 'nightly' && always() - with: - name: Cargo.lock - path: Cargo.lock - continue-on-error: true - - doc: - name: Documentation - runs-on: ubuntu-latest - timeout-minutes: 45 - env: - RUSTDOCFLAGS: -Dwarnings - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@nightly - - uses: dtolnay/install@cargo-docs-rs - - run: cargo docs-rs - - clippy: - name: Clippy - runs-on: ubuntu-latest - timeout-minutes: 45 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@clippy - - run: cargo clippy -- -Dclippy::all - - outdated: - name: Outdated - runs-on: ubuntu-latest - if: github.event_name != 'pull_request' - timeout-minutes: 45 - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: dtolnay/install@cargo-outdated - - run: cargo outdated --workspace --exit-code 1 diff --git a/.gitignore b/.gitignore index e9e2199..4308d82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -/target/ -/Cargo.lock +target/ +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 730f626..5021abe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,19 +1,10 @@ [package] name = "serde-example" -version = "0.1.0" +version = "0.0.0" authors = ["David Tolnay "] -categories = ["encoding"] +license = "MIT/Apache-2.0" description = "An example Serializer and Deserializer data format for Serde" +repository = "https://github.com/serde-rs/example-format" documentation = "https://serde.rs/data-format.html" -edition = "2021" keywords = ["serde"] -license = "MIT OR Apache-2.0" -publish = false -repository = "https://github.com/serde-rs/example-format" -rust-version = "1.56" - -[dependencies] -serde = "1.0" - -[dev-dependencies] -serde_derive = "1.0" +categories = ["encoding"] diff --git a/LICENSE-APACHE b/LICENSE-APACHE deleted file mode 100644 index 1b5ec8b..0000000 --- a/LICENSE-APACHE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS diff --git a/LICENSE-MIT b/LICENSE-MIT deleted file mode 100644 index 31aa793..0000000 --- a/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index c80a925..0000000 --- a/README.md +++ /dev/null @@ -1,21 +0,0 @@ -Please refer to the Serde website under [**Writing a data format**] for a -discussion of this example code. - -[**Writing a data format**]: https://serde.rs/data-format.html - -
- -#### License - - -Licensed under either of Apache License, Version -2.0 or MIT license at your option. - - -
- - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in this crate by you, as defined in the Apache-2.0 license, shall -be dual licensed as above, without any additional terms or conditions. - diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index df99c69..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -max_width = 80 diff --git a/src/de.rs b/src/de.rs deleted file mode 100644 index 4440484..0000000 --- a/src/de.rs +++ /dev/null @@ -1,702 +0,0 @@ -// Copyright 2018 Serde Developers -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use crate::error::{Error, Result}; -use serde::de::{ - self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, - MapAccess, SeqAccess, VariantAccess, Visitor, -}; -use std::ops::{AddAssign, MulAssign, Neg}; - -pub struct Deserializer<'de> { - // This string starts with the input data and characters are truncated off - // the beginning as data is parsed. - input: &'de str, -} - -impl<'de> Deserializer<'de> { - // By convention, `Deserializer` constructors are named like `from_xyz`. - // That way basic use cases are satisfied by something like - // `serde_json::from_str(...)` while advanced use cases that require a - // deserializer can make one with `serde_json::Deserializer::from_str(...)`. - #[allow(clippy::should_implement_trait)] - pub fn from_str(input: &'de str) -> Self { - Deserializer { input } - } -} - -// By convention, the public API of a Serde deserializer is one or more -// `from_xyz` methods such as `from_str`, `from_bytes`, or `from_reader` -// depending on what Rust types the deserializer is able to consume as input. -// -// This basic deserializer supports only `from_str`. -pub fn from_str<'a, T>(s: &'a str) -> Result -where - T: Deserialize<'a>, -{ - let mut deserializer = Deserializer::from_str(s); - let t = T::deserialize(&mut deserializer)?; - if deserializer.input.is_empty() { - Ok(t) - } else { - Err(Error::TrailingCharacters) - } -} - -// SERDE IS NOT A PARSING LIBRARY. This impl block defines a few basic parsing -// functions from scratch. More complicated formats may wish to use a dedicated -// parsing library to help implement their Serde deserializer. -impl<'de> Deserializer<'de> { - // Look at the first character in the input without consuming it. - fn peek_char(&mut self) -> Result { - self.input.chars().next().ok_or(Error::Eof) - } - - // Consume the first character in the input. - fn next_char(&mut self) -> Result { - let ch = self.peek_char()?; - self.input = &self.input[ch.len_utf8()..]; - Ok(ch) - } - - // Parse the JSON identifier `true` or `false`. - fn parse_bool(&mut self) -> Result { - if self.input.starts_with("true") { - self.input = &self.input["true".len()..]; - Ok(true) - } else if self.input.starts_with("false") { - self.input = &self.input["false".len()..]; - Ok(false) - } else { - Err(Error::ExpectedBoolean) - } - } - - // Parse a group of decimal digits as an unsigned integer of type T. - // - // This implementation is a bit too lenient, for example `001` is not - // allowed in JSON. Also the various arithmetic operations can overflow and - // panic or return bogus data. But it is good enough for example code! - fn parse_unsigned(&mut self) -> Result - where - T: AddAssign + MulAssign + From, - { - let mut int = match self.next_char()? { - ch @ '0'..='9' => T::from(ch as u8 - b'0'), - _ => { - return Err(Error::ExpectedInteger); - } - }; - loop { - match self.input.chars().next() { - Some(ch @ '0'..='9') => { - self.input = &self.input[1..]; - int *= T::from(10); - int += T::from(ch as u8 - b'0'); - } - _ => { - return Ok(int); - } - } - } - } - - // Parse a possible minus sign followed by a group of decimal digits as a - // signed integer of type T. - fn parse_signed(&mut self) -> Result - where - T: Neg + AddAssign + MulAssign + From, - { - // Optional minus sign, delegate to `parse_unsigned`, negate if negative. - unimplemented!() - } - - // Parse a string until the next '"' character. - // - // Makes no attempt to handle escape sequences. What did you expect? This is - // example code! - fn parse_string(&mut self) -> Result<&'de str> { - if self.next_char()? != '"' { - return Err(Error::ExpectedString); - } - match self.input.find('"') { - Some(len) => { - let s = &self.input[..len]; - self.input = &self.input[len + 1..]; - Ok(s) - } - None => Err(Error::Eof), - } - } -} - -impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> { - type Error = Error; - - // Look at the input data to decide what Serde data model type to - // deserialize as. Not all data formats are able to support this operation. - // Formats that support `deserialize_any` are known as self-describing. - fn deserialize_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - match self.peek_char()? { - 'n' => self.deserialize_unit(visitor), - 't' | 'f' => self.deserialize_bool(visitor), - '"' => self.deserialize_str(visitor), - '0'..='9' => self.deserialize_u64(visitor), - '-' => self.deserialize_i64(visitor), - '[' => self.deserialize_seq(visitor), - '{' => self.deserialize_map(visitor), - _ => Err(Error::Syntax), - } - } - - // Uses the `parse_bool` parsing function defined above to read the JSON - // identifier `true` or `false` from the input. - // - // Parsing refers to looking at the input and deciding that it contains the - // JSON value `true` or `false`. - // - // Deserialization refers to mapping that JSON value into Serde's data - // model by invoking one of the `Visitor` methods. In the case of JSON and - // bool that mapping is straightforward so the distinction may seem silly, - // but in other cases Deserializers sometimes perform non-obvious mappings. - // For example the TOML format has a Datetime type and Serde's data model - // does not. In the `toml` crate, a Datetime in the input is deserialized by - // mapping it to a Serde data model "struct" type with a special name and a - // single field containing the Datetime represented as a string. - fn deserialize_bool(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_bool(self.parse_bool()?) - } - - // The `parse_signed` function is generic over the integer type `T` so here - // it is invoked with `T=i8`. The next 8 methods are similar. - fn deserialize_i8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i8(self.parse_signed()?) - } - - fn deserialize_i16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i16(self.parse_signed()?) - } - - fn deserialize_i32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i32(self.parse_signed()?) - } - - fn deserialize_i64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_i64(self.parse_signed()?) - } - - fn deserialize_u8(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u8(self.parse_unsigned()?) - } - - fn deserialize_u16(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u16(self.parse_unsigned()?) - } - - fn deserialize_u32(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u32(self.parse_unsigned()?) - } - - fn deserialize_u64(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_u64(self.parse_unsigned()?) - } - - // Float parsing is stupidly hard. - fn deserialize_f32(self, _visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - // Float parsing is stupidly hard. - fn deserialize_f64(self, _visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - // The `Serializer` implementation on the previous page serialized chars as - // single-character strings so handle that representation here. - fn deserialize_char(self, _visitor: V) -> Result - where - V: Visitor<'de>, - { - // Parse a string, check that it is one character, call `visit_char`. - unimplemented!() - } - - // Refer to the "Understanding deserializer lifetimes" page for information - // about the three deserialization flavors of strings in Serde. - fn deserialize_str(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - visitor.visit_borrowed_str(self.parse_string()?) - } - - fn deserialize_string(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_str(visitor) - } - - // The `Serializer` implementation on the previous page serialized byte - // arrays as JSON arrays of bytes. Handle that representation here. - fn deserialize_bytes(self, _visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - fn deserialize_byte_buf(self, _visitor: V) -> Result - where - V: Visitor<'de>, - { - unimplemented!() - } - - // An absent optional is represented as the JSON `null` and a present - // optional is represented as just the contained value. - // - // As commented in `Serializer` implementation, this is a lossy - // representation. For example the values `Some(())` and `None` both - // serialize as just `null`. Unfortunately this is typically what people - // expect when working with JSON. Other formats are encouraged to behave - // more intelligently if possible. - fn deserialize_option(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - if self.input.starts_with("null") { - self.input = &self.input["null".len()..]; - visitor.visit_none() - } else { - visitor.visit_some(self) - } - } - - // In Serde, unit means an anonymous value containing no data. - fn deserialize_unit(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - if self.input.starts_with("null") { - self.input = &self.input["null".len()..]; - visitor.visit_unit() - } else { - Err(Error::ExpectedNull) - } - } - - // Unit struct means a named value containing no data. - fn deserialize_unit_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.deserialize_unit(visitor) - } - - // As is done here, serializers are encouraged to treat newtype structs as - // insignificant wrappers around the data they contain. That means not - // parsing anything other than the contained value. - fn deserialize_newtype_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - visitor.visit_newtype_struct(self) - } - - // Deserialization of compound types like sequences and maps happens by - // passing the visitor an "Access" object that gives it the ability to - // iterate through the data contained in the sequence. - fn deserialize_seq(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - // Parse the opening bracket of the sequence. - if self.next_char()? == '[' { - // Give the visitor access to each element of the sequence. - let value = visitor.visit_seq(CommaSeparated::new(self))?; - // Parse the closing bracket of the sequence. - if self.next_char()? == ']' { - Ok(value) - } else { - Err(Error::ExpectedArrayEnd) - } - } else { - Err(Error::ExpectedArray) - } - } - - // Tuples look just like sequences in JSON. Some formats may be able to - // represent tuples more efficiently. - // - // As indicated by the length parameter, the `Deserialize` implementation - // for a tuple in the Serde data model is required to know the length of the - // tuple before even looking at the input data. - fn deserialize_tuple(self, _len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - // Tuple structs look just like sequences in JSON. - fn deserialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.deserialize_seq(visitor) - } - - // Much like `deserialize_seq` but calls the visitors `visit_map` method - // with a `MapAccess` implementation, rather than the visitor's `visit_seq` - // method with a `SeqAccess` implementation. - fn deserialize_map(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - // Parse the opening brace of the map. - if self.next_char()? == '{' { - // Give the visitor access to each entry of the map. - let value = visitor.visit_map(CommaSeparated::new(self))?; - // Parse the closing brace of the map. - if self.next_char()? == '}' { - Ok(value) - } else { - Err(Error::ExpectedMapEnd) - } - } else { - Err(Error::ExpectedMap) - } - } - - // Structs look just like maps in JSON. - // - // Notice the `fields` parameter - a "struct" in the Serde data model means - // that the `Deserialize` implementation is required to know what the fields - // are before even looking at the input data. Any key-value pairing in which - // the fields cannot be known ahead of time is probably a map. - fn deserialize_struct( - self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - self.deserialize_map(visitor) - } - - fn deserialize_enum( - self, - _name: &'static str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - if self.peek_char()? == '"' { - // Visit a unit variant. - visitor.visit_enum(self.parse_string()?.into_deserializer()) - } else if self.next_char()? == '{' { - // Visit a newtype variant, tuple variant, or struct variant. - let value = visitor.visit_enum(Enum::new(self))?; - // Parse the matching close brace. - if self.next_char()? == '}' { - Ok(value) - } else { - Err(Error::ExpectedMapEnd) - } - } else { - Err(Error::ExpectedEnum) - } - } - - // An identifier in Serde is the type that identifies a field of a struct or - // the variant of an enum. In JSON, struct fields and enum variants are - // represented as strings. In other formats they may be represented as - // numeric indices. - fn deserialize_identifier(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_str(visitor) - } - - // Like `deserialize_any` but indicates to the `Deserializer` that it makes - // no difference which `Visitor` method is called because the data is - // ignored. - // - // Some deserializers are able to implement this more efficiently than - // `deserialize_any`, for example by rapidly skipping over matched - // delimiters without paying close attention to the data in between. - // - // Some formats are not able to implement this at all. Formats that can - // implement `deserialize_any` and `deserialize_ignored_any` are known as - // self-describing. - fn deserialize_ignored_any(self, visitor: V) -> Result - where - V: Visitor<'de>, - { - self.deserialize_any(visitor) - } -} - -// In order to handle commas correctly when deserializing a JSON array or map, -// we need to track whether we are on the first element or past the first -// element. -struct CommaSeparated<'a, 'de: 'a> { - de: &'a mut Deserializer<'de>, - first: bool, -} - -impl<'a, 'de> CommaSeparated<'a, 'de> { - fn new(de: &'a mut Deserializer<'de>) -> Self { - CommaSeparated { de, first: true } - } -} - -// `SeqAccess` is provided to the `Visitor` to give it the ability to iterate -// through elements of the sequence. -impl<'de> SeqAccess<'de> for CommaSeparated<'_, 'de> { - type Error = Error; - - fn next_element_seed(&mut self, seed: T) -> Result> - where - T: DeserializeSeed<'de>, - { - // Check if there are no more elements. - if self.de.peek_char()? == ']' { - return Ok(None); - } - // Comma is required before every element except the first. - if !self.first && self.de.next_char()? != ',' { - return Err(Error::ExpectedArrayComma); - } - self.first = false; - // Deserialize an array element. - seed.deserialize(&mut *self.de).map(Some) - } -} - -// `MapAccess` is provided to the `Visitor` to give it the ability to iterate -// through entries of the map. -impl<'de> MapAccess<'de> for CommaSeparated<'_, 'de> { - type Error = Error; - - fn next_key_seed(&mut self, seed: K) -> Result> - where - K: DeserializeSeed<'de>, - { - // Check if there are no more entries. - if self.de.peek_char()? == '}' { - return Ok(None); - } - // Comma is required before every entry except the first. - if !self.first && self.de.next_char()? != ',' { - return Err(Error::ExpectedMapComma); - } - self.first = false; - // Deserialize a map key. - seed.deserialize(&mut *self.de).map(Some) - } - - fn next_value_seed(&mut self, seed: V) -> Result - where - V: DeserializeSeed<'de>, - { - // It doesn't make a difference whether the colon is parsed at the end - // of `next_key_seed` or at the beginning of `next_value_seed`. In this - // case the code is a bit simpler having it here. - if self.de.next_char()? != ':' { - return Err(Error::ExpectedMapColon); - } - // Deserialize a map value. - seed.deserialize(&mut *self.de) - } -} - -struct Enum<'a, 'de: 'a> { - de: &'a mut Deserializer<'de>, -} - -impl<'a, 'de> Enum<'a, 'de> { - fn new(de: &'a mut Deserializer<'de>) -> Self { - Enum { de } - } -} - -// `EnumAccess` is provided to the `Visitor` to give it the ability to determine -// which variant of the enum is supposed to be deserialized. -// -// Note that all enum deserialization methods in Serde refer exclusively to the -// "externally tagged" enum representation. -impl<'de> EnumAccess<'de> for Enum<'_, 'de> { - type Error = Error; - type Variant = Self; - - fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> - where - V: DeserializeSeed<'de>, - { - // The `deserialize_enum` method parsed a `{` character so we are - // currently inside of a map. The seed will be deserializing itself from - // the key of the map. - let val = seed.deserialize(&mut *self.de)?; - // Parse the colon separating map key from value. - if self.de.next_char()? == ':' { - Ok((val, self)) - } else { - Err(Error::ExpectedMapColon) - } - } -} - -// `VariantAccess` is provided to the `Visitor` to give it the ability to see -// the content of the single variant that it decided to deserialize. -impl<'de> VariantAccess<'de> for Enum<'_, 'de> { - type Error = Error; - - // If the `Visitor` expected this variant to be a unit variant, the input - // should have been the plain string case handled in `deserialize_enum`. - fn unit_variant(self) -> Result<()> { - Err(Error::ExpectedString) - } - - // Newtype variants are represented in JSON as `{ NAME: VALUE }` so - // deserialize the value here. - fn newtype_variant_seed(self, seed: T) -> Result - where - T: DeserializeSeed<'de>, - { - seed.deserialize(self.de) - } - - // Tuple variants are represented in JSON as `{ NAME: [DATA...] }` so - // deserialize the sequence of data here. - fn tuple_variant(self, _len: usize, visitor: V) -> Result - where - V: Visitor<'de>, - { - de::Deserializer::deserialize_seq(self.de, visitor) - } - - // Struct variants are represented in JSON as `{ NAME: { K: V, ... } }` so - // deserialize the inner map here. - fn struct_variant( - self, - _fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: Visitor<'de>, - { - de::Deserializer::deserialize_map(self.de, visitor) - } -} - -//////////////////////////////////////////////////////////////////////////////// - -#[cfg(test)] -mod tests { - use super::from_str; - use serde_derive::Deserialize; - - #[test] - fn test_struct() { - #[derive(Deserialize, PartialEq, Debug)] - struct Test { - int: u32, - seq: Vec, - } - - let j = r#"{"int":1,"seq":["a","b"]}"#; - let expected = Test { - int: 1, - seq: vec!["a".to_owned(), "b".to_owned()], - }; - assert_eq!(expected, from_str(j).unwrap()); - } - - #[test] - fn test_enum() { - #[derive(Deserialize, PartialEq, Debug)] - enum E { - Unit, - Newtype(u32), - Tuple(u32, u32), - Struct { a: u32 }, - } - - let j = r#""Unit""#; - let expected = E::Unit; - assert_eq!(expected, from_str(j).unwrap()); - - let j = r#"{"Newtype":1}"#; - let expected = E::Newtype(1); - assert_eq!(expected, from_str(j).unwrap()); - - let j = r#"{"Tuple":[1,2]}"#; - let expected = E::Tuple(1, 2); - assert_eq!(expected, from_str(j).unwrap()); - - let j = r#"{"Struct":{"a":1}}"#; - let expected = E::Struct { a: 1 }; - assert_eq!(expected, from_str(j).unwrap()); - } -} diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index ab175bc..0000000 --- a/src/error.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2018 Serde Developers -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use serde::{de, ser}; -use std::fmt::{self, Display}; - -pub type Result = std::result::Result; - -// This is a bare-bones implementation. A real library would provide additional -// information in its error type, for example the line and column at which the -// error occurred, the byte offset into the input, or the current key being -// processed. -#[derive(Debug)] -pub enum Error { - // One or more variants that can be created by data structures through the - // `ser::Error` and `de::Error` traits. For example the Serialize impl for - // Mutex might return an error because the mutex is poisoned, or the - // Deserialize impl for a struct may return an error because a required - // field is missing. - Message(String), - - // Zero or more variants that can be created directly by the Serializer and - // Deserializer without going through `ser::Error` and `de::Error`. These - // are specific to the format, in this case JSON. - Eof, - Syntax, - ExpectedBoolean, - ExpectedInteger, - ExpectedString, - ExpectedNull, - ExpectedArray, - ExpectedArrayComma, - ExpectedArrayEnd, - ExpectedMap, - ExpectedMapColon, - ExpectedMapComma, - ExpectedMapEnd, - ExpectedEnum, - TrailingCharacters, -} - -impl ser::Error for Error { - fn custom(msg: T) -> Self { - Error::Message(msg.to_string()) - } -} - -impl de::Error for Error { - fn custom(msg: T) -> Self { - Error::Message(msg.to_string()) - } -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::Message(msg) => write!(f, "{}", msg), - Error::Eof => f.write_str("unexpected end of input"), - /* and so forth */ - _ => unimplemented!(), - } - } -} - -impl std::error::Error for Error {} diff --git a/src/lib.rs b/src/lib.rs index 14326f3..59c227c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1 @@ -// Copyright 2018 Serde Developers -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod de; -mod error; -mod ser; - -pub use crate::de::{from_str, Deserializer}; -pub use crate::error::{Error, Result}; -pub use crate::ser::{to_string, Serializer}; +@ diff --git a/src/ser.rs b/src/ser.rs deleted file mode 100644 index 76dc6af..0000000 --- a/src/ser.rs +++ /dev/null @@ -1,550 +0,0 @@ -// Copyright 2018 Serde Developers -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use crate::error::{Error, Result}; -use serde::ser::{self, Serialize}; - -pub struct Serializer { - // This string starts empty and JSON is appended as values are serialized. - output: String, -} - -// By convention, the public API of a Serde serializer is one or more `to_abc` -// functions such as `to_string`, `to_bytes`, or `to_writer` depending on what -// Rust types the serializer is able to produce as output. -// -// This basic serializer supports only `to_string`. -pub fn to_string(value: &T) -> Result -where - T: Serialize, -{ - let mut serializer = Serializer { - output: String::new(), - }; - value.serialize(&mut serializer)?; - Ok(serializer.output) -} - -impl ser::Serializer for &mut Serializer { - // The output type produced by this `Serializer` during successful - // serialization. Most serializers that produce text or binary output should - // set `Ok = ()` and serialize into an `io::Write` or buffer contained - // within the `Serializer` instance, as happens here. Serializers that build - // in-memory data structures may be simplified by using `Ok` to propagate - // the data structure around. - type Ok = (); - - // The error type when some error occurs during serialization. - type Error = Error; - - // Associated types for keeping track of additional state while serializing - // compound data structures like sequences and maps. In this case no - // additional state is required beyond what is already stored in the - // Serializer struct. - type SerializeSeq = Self; - type SerializeTuple = Self; - type SerializeTupleStruct = Self; - type SerializeTupleVariant = Self; - type SerializeMap = Self; - type SerializeStruct = Self; - type SerializeStructVariant = Self; - - // Here we go with the simple methods. The following 12 methods receive one - // of the primitive types of the data model and map it to JSON by appending - // into the output string. - fn serialize_bool(self, v: bool) -> Result<()> { - self.output += if v { "true" } else { "false" }; - Ok(()) - } - - // JSON does not distinguish between different sizes of integers, so all - // signed integers will be serialized the same and all unsigned integers - // will be serialized the same. Other formats, especially compact binary - // formats, may need independent logic for the different sizes. - fn serialize_i8(self, v: i8) -> Result<()> { - self.serialize_i64(i64::from(v)) - } - - fn serialize_i16(self, v: i16) -> Result<()> { - self.serialize_i64(i64::from(v)) - } - - fn serialize_i32(self, v: i32) -> Result<()> { - self.serialize_i64(i64::from(v)) - } - - // Not particularly efficient but this is example code anyway. A more - // performant approach would be to use the `itoa` crate. - fn serialize_i64(self, v: i64) -> Result<()> { - self.output += &v.to_string(); - Ok(()) - } - - fn serialize_u8(self, v: u8) -> Result<()> { - self.serialize_u64(u64::from(v)) - } - - fn serialize_u16(self, v: u16) -> Result<()> { - self.serialize_u64(u64::from(v)) - } - - fn serialize_u32(self, v: u32) -> Result<()> { - self.serialize_u64(u64::from(v)) - } - - fn serialize_u64(self, v: u64) -> Result<()> { - self.output += &v.to_string(); - Ok(()) - } - - fn serialize_f32(self, v: f32) -> Result<()> { - self.serialize_f64(f64::from(v)) - } - - fn serialize_f64(self, v: f64) -> Result<()> { - self.output += &v.to_string(); - Ok(()) - } - - // Serialize a char as a single-character string. Other formats may - // represent this differently. - fn serialize_char(self, v: char) -> Result<()> { - self.serialize_str(&v.to_string()) - } - - // This only works for strings that don't require escape sequences but you - // get the idea. For example it would emit invalid JSON if the input string - // contains a '"' character. - fn serialize_str(self, v: &str) -> Result<()> { - self.output += "\""; - self.output += v; - self.output += "\""; - Ok(()) - } - - // Serialize a byte array as an array of bytes. Could also use a base64 - // string here. Binary formats will typically represent byte arrays more - // compactly. - fn serialize_bytes(self, v: &[u8]) -> Result<()> { - use serde::ser::SerializeSeq; - let mut seq = self.serialize_seq(Some(v.len()))?; - for byte in v { - seq.serialize_element(byte)?; - } - seq.end() - } - - // An absent optional is represented as the JSON `null`. - fn serialize_none(self) -> Result<()> { - self.serialize_unit() - } - - // A present optional is represented as just the contained value. Note that - // this is a lossy representation. For example the values `Some(())` and - // `None` both serialize as just `null`. Unfortunately this is typically - // what people expect when working with JSON. Other formats are encouraged - // to behave more intelligently if possible. - fn serialize_some(self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - value.serialize(self) - } - - // In Serde, unit means an anonymous value containing no data. Map this to - // JSON as `null`. - fn serialize_unit(self) -> Result<()> { - self.output += "null"; - Ok(()) - } - - // Unit struct means a named value containing no data. Again, since there is - // no data, map this to JSON as `null`. There is no need to serialize the - // name in most formats. - fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { - self.serialize_unit() - } - - // When serializing a unit variant (or any other kind of variant), formats - // can choose whether to keep track of it by index or by name. Binary - // formats typically use the index of the variant and human-readable formats - // typically use the name. - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> Result<()> { - self.serialize_str(variant) - } - - // As is done here, serializers are encouraged to treat newtype structs as - // insignificant wrappers around the data they contain. - fn serialize_newtype_struct( - self, - _name: &'static str, - value: &T, - ) -> Result<()> - where - T: ?Sized + Serialize, - { - value.serialize(self) - } - - // Note that newtype variant (and all of the other variant serialization - // methods) refer exclusively to the "externally tagged" enum - // representation. - // - // Serialize this to JSON in externally tagged form as `{ NAME: VALUE }`. - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result<()> - where - T: ?Sized + Serialize, - { - self.output += "{"; - variant.serialize(&mut *self)?; - self.output += ":"; - value.serialize(&mut *self)?; - self.output += "}"; - Ok(()) - } - - // Now we get to the serialization of compound types. - // - // The start of the sequence, each value, and the end are three separate - // method calls. This one is responsible only for serializing the start, - // which in JSON is `[`. - // - // The length of the sequence may or may not be known ahead of time. This - // doesn't make a difference in JSON because the length is not represented - // explicitly in the serialized form. Some serializers may only be able to - // support sequences for which the length is known up front. - fn serialize_seq(self, _len: Option) -> Result { - self.output += "["; - Ok(self) - } - - // Tuples look just like sequences in JSON. Some formats may be able to - // represent tuples more efficiently by omitting the length, since tuple - // means that the corresponding `Deserialize implementation will know the - // length without needing to look at the serialized data. - fn serialize_tuple(self, len: usize) -> Result { - self.serialize_seq(Some(len)) - } - - // Tuple structs look just like sequences in JSON. - fn serialize_tuple_struct( - self, - _name: &'static str, - len: usize, - ) -> Result { - self.serialize_seq(Some(len)) - } - - // Tuple variants are represented in JSON as `{ NAME: [DATA...] }`. Again - // this method is only responsible for the externally tagged representation. - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - self.output += "{"; - variant.serialize(&mut *self)?; - self.output += ":["; - Ok(self) - } - - // Maps are represented in JSON as `{ K: V, K: V, ... }`. - fn serialize_map(self, _len: Option) -> Result { - self.output += "{"; - Ok(self) - } - - // Structs look just like maps in JSON. In particular, JSON requires that we - // serialize the field names of the struct. Other formats may be able to - // omit the field names when serializing structs because the corresponding - // Deserialize implementation is required to know what the keys are without - // looking at the serialized data. - fn serialize_struct( - self, - _name: &'static str, - len: usize, - ) -> Result { - self.serialize_map(Some(len)) - } - - // Struct variants are represented in JSON as `{ NAME: { K: V, ... } }`. - // This is the externally tagged representation. - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - self.output += "{"; - variant.serialize(&mut *self)?; - self.output += ":{"; - Ok(self) - } -} - -// The following 7 impls deal with the serialization of compound types like -// sequences and maps. Serialization of such types is begun by a Serializer -// method and followed by zero or more calls to serialize individual elements of -// the compound type and one call to end the compound type. -// -// This impl is SerializeSeq so these methods are called after `serialize_seq` -// is called on the Serializer. -impl ser::SerializeSeq for &mut Serializer { - // Must match the `Ok` type of the serializer. - type Ok = (); - // Must match the `Error` type of the serializer. - type Error = Error; - - // Serialize a single element of the sequence. - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if !self.output.ends_with('[') { - self.output += ","; - } - value.serialize(&mut **self) - } - - // Close the sequence. - fn end(self) -> Result<()> { - self.output += "]"; - Ok(()) - } -} - -// Same thing but for tuples. -impl ser::SerializeTuple for &mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if !self.output.ends_with('[') { - self.output += ","; - } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.output += "]"; - Ok(()) - } -} - -// Same thing but for tuple structs. -impl ser::SerializeTupleStruct for &mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if !self.output.ends_with('[') { - self.output += ","; - } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.output += "]"; - Ok(()) - } -} - -// Tuple variants are a little different. Refer back to the -// `serialize_tuple_variant` method above: -// -// self.output += "{"; -// variant.serialize(&mut *self)?; -// self.output += ":["; -// -// So the `end` method in this impl is responsible for closing both the `]` and -// the `}`. -impl ser::SerializeTupleVariant for &mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if !self.output.ends_with('[') { - self.output += ","; - } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.output += "]}"; - Ok(()) - } -} - -// Some `Serialize` types are not able to hold a key and value in memory at the -// same time so `SerializeMap` implementations are required to support -// `serialize_key` and `serialize_value` individually. -// -// There is a third optional method on the `SerializeMap` trait. The -// `serialize_entry` method allows serializers to optimize for the case where -// key and value are both available simultaneously. In JSON it doesn't make a -// difference so the default behavior for `serialize_entry` is fine. -impl ser::SerializeMap for &mut Serializer { - type Ok = (); - type Error = Error; - - // The Serde data model allows map keys to be any serializable type. JSON - // only allows string keys so the implementation below will produce invalid - // JSON if the key serializes as something other than a string. - // - // A real JSON serializer would need to validate that map keys are strings. - // This can be done by using a different Serializer to serialize the key - // (instead of `&mut **self`) and having that other serializer only - // implement `serialize_str` and return an error on any other data type. - fn serialize_key(&mut self, key: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if !self.output.ends_with('{') { - self.output += ","; - } - key.serialize(&mut **self) - } - - // It doesn't make a difference whether the colon is printed at the end of - // `serialize_key` or at the beginning of `serialize_value`. In this case - // the code is a bit simpler having it here. - fn serialize_value(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - self.output += ":"; - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.output += "}"; - Ok(()) - } -} - -// Structs are like maps in which the keys are constrained to be compile-time -// constant strings. -impl ser::SerializeStruct for &mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if !self.output.ends_with('{') { - self.output += ","; - } - key.serialize(&mut **self)?; - self.output += ":"; - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.output += "}"; - Ok(()) - } -} - -// Similar to `SerializeTupleVariant`, here the `end` method is responsible for -// closing both of the curly braces opened by `serialize_struct_variant`. -impl ser::SerializeStructVariant for &mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if !self.output.ends_with('{') { - self.output += ","; - } - key.serialize(&mut **self)?; - self.output += ":"; - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.output += "}}"; - Ok(()) - } -} - -//////////////////////////////////////////////////////////////////////////////// - -#[cfg(test)] -mod tests { - use super::to_string; - use serde_derive::Serialize; - - #[test] - fn test_struct() { - #[derive(Serialize)] - struct Test { - int: u32, - seq: Vec<&'static str>, - } - - let test = Test { - int: 1, - seq: vec!["a", "b"], - }; - let expected = r#"{"int":1,"seq":["a","b"]}"#; - assert_eq!(to_string(&test).unwrap(), expected); - } - - #[test] - fn test_enum() { - #[derive(Serialize)] - enum E { - Unit, - Newtype(u32), - Tuple(u32, u32), - Struct { a: u32 }, - } - - let u = E::Unit; - let expected = r#""Unit""#; - assert_eq!(to_string(&u).unwrap(), expected); - - let n = E::Newtype(1); - let expected = r#"{"Newtype":1}"#; - assert_eq!(to_string(&n).unwrap(), expected); - - let t = E::Tuple(1, 2); - let expected = r#"{"Tuple":[1,2]}"#; - assert_eq!(to_string(&t).unwrap(), expected); - - let s = E::Struct { a: 1 }; - let expected = r#"{"Struct":{"a":1}}"#; - assert_eq!(to_string(&s).unwrap(), expected); - } -}