1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::borrow::Cow;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Debug;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Display;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::num::ParseIntError;
10*bb4ee6a4SAndroid Build Coastguard Worker
11*bb4ee6a4SAndroid Build Coastguard Worker use nom::branch::alt;
12*bb4ee6a4SAndroid Build Coastguard Worker use nom::bytes::complete::escaped_transform;
13*bb4ee6a4SAndroid Build Coastguard Worker use nom::bytes::complete::is_not;
14*bb4ee6a4SAndroid Build Coastguard Worker use nom::bytes::complete::tag;
15*bb4ee6a4SAndroid Build Coastguard Worker use nom::bytes::complete::take_while;
16*bb4ee6a4SAndroid Build Coastguard Worker use nom::bytes::complete::take_while1;
17*bb4ee6a4SAndroid Build Coastguard Worker use nom::character::complete::alphanumeric1;
18*bb4ee6a4SAndroid Build Coastguard Worker use nom::character::complete::anychar;
19*bb4ee6a4SAndroid Build Coastguard Worker use nom::character::complete::char;
20*bb4ee6a4SAndroid Build Coastguard Worker use nom::character::complete::none_of;
21*bb4ee6a4SAndroid Build Coastguard Worker use nom::combinator::map;
22*bb4ee6a4SAndroid Build Coastguard Worker use nom::combinator::map_res;
23*bb4ee6a4SAndroid Build Coastguard Worker use nom::combinator::opt;
24*bb4ee6a4SAndroid Build Coastguard Worker use nom::combinator::peek;
25*bb4ee6a4SAndroid Build Coastguard Worker use nom::combinator::recognize;
26*bb4ee6a4SAndroid Build Coastguard Worker use nom::combinator::value;
27*bb4ee6a4SAndroid Build Coastguard Worker use nom::combinator::verify;
28*bb4ee6a4SAndroid Build Coastguard Worker use nom::sequence::delimited;
29*bb4ee6a4SAndroid Build Coastguard Worker use nom::sequence::pair;
30*bb4ee6a4SAndroid Build Coastguard Worker use nom::sequence::tuple;
31*bb4ee6a4SAndroid Build Coastguard Worker use nom::AsChar;
32*bb4ee6a4SAndroid Build Coastguard Worker use nom::Finish;
33*bb4ee6a4SAndroid Build Coastguard Worker use nom::IResult;
34*bb4ee6a4SAndroid Build Coastguard Worker use num_traits::Num;
35*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
36*bb4ee6a4SAndroid Build Coastguard Worker use serde::de;
37*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
38*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserializer;
39*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
40*bb4ee6a4SAndroid Build Coastguard Worker
41*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Error, PartialEq, Eq)]
42*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
43*bb4ee6a4SAndroid Build Coastguard Worker #[non_exhaustive]
44*bb4ee6a4SAndroid Build Coastguard Worker #[allow(missing_docs)]
45*bb4ee6a4SAndroid Build Coastguard Worker /// Different kinds of errors that can be returned by the parser.
46*bb4ee6a4SAndroid Build Coastguard Worker pub enum ErrorKind {
47*bb4ee6a4SAndroid Build Coastguard Worker #[error("unexpected end of input")]
48*bb4ee6a4SAndroid Build Coastguard Worker Eof,
49*bb4ee6a4SAndroid Build Coastguard Worker #[error("expected a boolean")]
50*bb4ee6a4SAndroid Build Coastguard Worker ExpectedBoolean,
51*bb4ee6a4SAndroid Build Coastguard Worker #[error("expected ']'")]
52*bb4ee6a4SAndroid Build Coastguard Worker ExpectedCloseBracket,
53*bb4ee6a4SAndroid Build Coastguard Worker #[error("expected ','")]
54*bb4ee6a4SAndroid Build Coastguard Worker ExpectedComma,
55*bb4ee6a4SAndroid Build Coastguard Worker #[error("expected '='")]
56*bb4ee6a4SAndroid Build Coastguard Worker ExpectedEqual,
57*bb4ee6a4SAndroid Build Coastguard Worker #[error("expected an identifier")]
58*bb4ee6a4SAndroid Build Coastguard Worker ExpectedIdentifier,
59*bb4ee6a4SAndroid Build Coastguard Worker #[error("expected '['")]
60*bb4ee6a4SAndroid Build Coastguard Worker ExpectedOpenBracket,
61*bb4ee6a4SAndroid Build Coastguard Worker #[error("expected a string")]
62*bb4ee6a4SAndroid Build Coastguard Worker ExpectedString,
63*bb4ee6a4SAndroid Build Coastguard Worker #[error("\" and ' can only be used in quoted strings")]
64*bb4ee6a4SAndroid Build Coastguard Worker InvalidCharInString,
65*bb4ee6a4SAndroid Build Coastguard Worker #[error("invalid characters for number or number does not fit into its destination type")]
66*bb4ee6a4SAndroid Build Coastguard Worker InvalidNumber,
67*bb4ee6a4SAndroid Build Coastguard Worker #[error("serde error: {0}")]
68*bb4ee6a4SAndroid Build Coastguard Worker SerdeError(String),
69*bb4ee6a4SAndroid Build Coastguard Worker #[error("remaining characters in input")]
70*bb4ee6a4SAndroid Build Coastguard Worker TrailingCharacters,
71*bb4ee6a4SAndroid Build Coastguard Worker }
72*bb4ee6a4SAndroid Build Coastguard Worker
73*bb4ee6a4SAndroid Build Coastguard Worker /// Error that may be thown while parsing a key-values string.
74*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Error, PartialEq, Eq)]
75*bb4ee6a4SAndroid Build Coastguard Worker pub struct ParseError {
76*bb4ee6a4SAndroid Build Coastguard Worker /// Detailed error that occurred.
77*bb4ee6a4SAndroid Build Coastguard Worker pub kind: ErrorKind,
78*bb4ee6a4SAndroid Build Coastguard Worker /// Index of the error in the input string.
79*bb4ee6a4SAndroid Build Coastguard Worker pub pos: usize,
80*bb4ee6a4SAndroid Build Coastguard Worker }
81*bb4ee6a4SAndroid Build Coastguard Worker
82*bb4ee6a4SAndroid Build Coastguard Worker impl Display for ParseError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result83*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84*bb4ee6a4SAndroid Build Coastguard Worker match &self.kind {
85*bb4ee6a4SAndroid Build Coastguard Worker ErrorKind::SerdeError(s) => write!(f, "{}", s),
86*bb4ee6a4SAndroid Build Coastguard Worker _ => write!(f, "{} at position {}", self.kind, self.pos),
87*bb4ee6a4SAndroid Build Coastguard Worker }
88*bb4ee6a4SAndroid Build Coastguard Worker }
89*bb4ee6a4SAndroid Build Coastguard Worker }
90*bb4ee6a4SAndroid Build Coastguard Worker
91*bb4ee6a4SAndroid Build Coastguard Worker impl de::Error for ParseError {
custom<T>(msg: T) -> Self where T: fmt::Display,92*bb4ee6a4SAndroid Build Coastguard Worker fn custom<T>(msg: T) -> Self
93*bb4ee6a4SAndroid Build Coastguard Worker where
94*bb4ee6a4SAndroid Build Coastguard Worker T: fmt::Display,
95*bb4ee6a4SAndroid Build Coastguard Worker {
96*bb4ee6a4SAndroid Build Coastguard Worker Self {
97*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::SerdeError(msg.to_string()),
98*bb4ee6a4SAndroid Build Coastguard Worker pos: 0,
99*bb4ee6a4SAndroid Build Coastguard Worker }
100*bb4ee6a4SAndroid Build Coastguard Worker }
101*bb4ee6a4SAndroid Build Coastguard Worker }
102*bb4ee6a4SAndroid Build Coastguard Worker
103*bb4ee6a4SAndroid Build Coastguard Worker type Result<T> = std::result::Result<T, ParseError>;
104*bb4ee6a4SAndroid Build Coastguard Worker
105*bb4ee6a4SAndroid Build Coastguard Worker /// Returns `true` if `c` is a valid separator character.
is_separator(c: Option<char>) -> bool106*bb4ee6a4SAndroid Build Coastguard Worker fn is_separator(c: Option<char>) -> bool {
107*bb4ee6a4SAndroid Build Coastguard Worker matches!(c, Some(',') | Some(']') | None)
108*bb4ee6a4SAndroid Build Coastguard Worker }
109*bb4ee6a4SAndroid Build Coastguard Worker
110*bb4ee6a4SAndroid Build Coastguard Worker /// Nom parser for valid separators.
any_separator(s: &str) -> IResult<&str, Option<char>>111*bb4ee6a4SAndroid Build Coastguard Worker fn any_separator(s: &str) -> IResult<&str, Option<char>> {
112*bb4ee6a4SAndroid Build Coastguard Worker let next_char = s.chars().next();
113*bb4ee6a4SAndroid Build Coastguard Worker
114*bb4ee6a4SAndroid Build Coastguard Worker if is_separator(next_char) {
115*bb4ee6a4SAndroid Build Coastguard Worker let pos = if let Some(c) = next_char {
116*bb4ee6a4SAndroid Build Coastguard Worker c.len_utf8()
117*bb4ee6a4SAndroid Build Coastguard Worker } else {
118*bb4ee6a4SAndroid Build Coastguard Worker 0
119*bb4ee6a4SAndroid Build Coastguard Worker };
120*bb4ee6a4SAndroid Build Coastguard Worker Ok((&s[pos..], next_char))
121*bb4ee6a4SAndroid Build Coastguard Worker } else {
122*bb4ee6a4SAndroid Build Coastguard Worker Err(nom::Err::Error(nom::error::Error::new(
123*bb4ee6a4SAndroid Build Coastguard Worker s,
124*bb4ee6a4SAndroid Build Coastguard Worker nom::error::ErrorKind::Char,
125*bb4ee6a4SAndroid Build Coastguard Worker )))
126*bb4ee6a4SAndroid Build Coastguard Worker }
127*bb4ee6a4SAndroid Build Coastguard Worker }
128*bb4ee6a4SAndroid Build Coastguard Worker
129*bb4ee6a4SAndroid Build Coastguard Worker /// Nom parser for valid strings.
130*bb4ee6a4SAndroid Build Coastguard Worker ///
131*bb4ee6a4SAndroid Build Coastguard Worker /// A string can be quoted (using single or double quotes) or not. If it is not quoted, the string
132*bb4ee6a4SAndroid Build Coastguard Worker /// is assumed to continue until the next ',', '[', or ']' character. If it is escaped, it continues
133*bb4ee6a4SAndroid Build Coastguard Worker /// until the next non-escaped quote.
134*bb4ee6a4SAndroid Build Coastguard Worker ///
135*bb4ee6a4SAndroid Build Coastguard Worker /// The returned value is a slice into the current input if no characters to unescape were met,
136*bb4ee6a4SAndroid Build Coastguard Worker /// or a fully owned string if we had to unescape some characters.
any_string(s: &str) -> IResult<&str, Cow<str>>137*bb4ee6a4SAndroid Build Coastguard Worker fn any_string(s: &str) -> IResult<&str, Cow<str>> {
138*bb4ee6a4SAndroid Build Coastguard Worker // Double-quoted strings may escape " and \ characters. Since escaped strings are modified,
139*bb4ee6a4SAndroid Build Coastguard Worker // we need to return an owned `String` instead of just a slice in the input string.
140*bb4ee6a4SAndroid Build Coastguard Worker let double_quoted = delimited(
141*bb4ee6a4SAndroid Build Coastguard Worker char('"'),
142*bb4ee6a4SAndroid Build Coastguard Worker alt((
143*bb4ee6a4SAndroid Build Coastguard Worker map(
144*bb4ee6a4SAndroid Build Coastguard Worker escaped_transform(
145*bb4ee6a4SAndroid Build Coastguard Worker none_of(r#"\""#),
146*bb4ee6a4SAndroid Build Coastguard Worker '\\',
147*bb4ee6a4SAndroid Build Coastguard Worker alt((value("\"", char('"')), value("\\", char('\\')))),
148*bb4ee6a4SAndroid Build Coastguard Worker ),
149*bb4ee6a4SAndroid Build Coastguard Worker Cow::Owned,
150*bb4ee6a4SAndroid Build Coastguard Worker ),
151*bb4ee6a4SAndroid Build Coastguard Worker map(tag(""), Cow::Borrowed),
152*bb4ee6a4SAndroid Build Coastguard Worker )),
153*bb4ee6a4SAndroid Build Coastguard Worker char('"'),
154*bb4ee6a4SAndroid Build Coastguard Worker );
155*bb4ee6a4SAndroid Build Coastguard Worker
156*bb4ee6a4SAndroid Build Coastguard Worker // Single-quoted strings do not escape characters.
157*bb4ee6a4SAndroid Build Coastguard Worker let single_quoted = map(
158*bb4ee6a4SAndroid Build Coastguard Worker delimited(char('\''), alt((is_not(r#"'"#), tag(""))), char('\'')),
159*bb4ee6a4SAndroid Build Coastguard Worker Cow::Borrowed,
160*bb4ee6a4SAndroid Build Coastguard Worker );
161*bb4ee6a4SAndroid Build Coastguard Worker
162*bb4ee6a4SAndroid Build Coastguard Worker // Unquoted strings end with the next comma or bracket and may not contain a quote or bracket
163*bb4ee6a4SAndroid Build Coastguard Worker // character or be empty.
164*bb4ee6a4SAndroid Build Coastguard Worker let unquoted = map(
165*bb4ee6a4SAndroid Build Coastguard Worker take_while1(|c: char| c != ',' && c != '"' && c != '\'' && c != '[' && c != ']'),
166*bb4ee6a4SAndroid Build Coastguard Worker Cow::Borrowed,
167*bb4ee6a4SAndroid Build Coastguard Worker );
168*bb4ee6a4SAndroid Build Coastguard Worker
169*bb4ee6a4SAndroid Build Coastguard Worker alt((double_quoted, single_quoted, unquoted))(s)
170*bb4ee6a4SAndroid Build Coastguard Worker }
171*bb4ee6a4SAndroid Build Coastguard Worker
172*bb4ee6a4SAndroid Build Coastguard Worker /// Nom parser for valid positive of negative numbers.
173*bb4ee6a4SAndroid Build Coastguard Worker ///
174*bb4ee6a4SAndroid Build Coastguard Worker /// Hexadecimal, octal, and binary values can be specified with the `0x`, `0o` and `0b` prefixes.
any_number<T>(s: &str) -> IResult<&str, T> where T: Num<FromStrRadixErr = ParseIntError>,175*bb4ee6a4SAndroid Build Coastguard Worker fn any_number<T>(s: &str) -> IResult<&str, T>
176*bb4ee6a4SAndroid Build Coastguard Worker where
177*bb4ee6a4SAndroid Build Coastguard Worker T: Num<FromStrRadixErr = ParseIntError>,
178*bb4ee6a4SAndroid Build Coastguard Worker {
179*bb4ee6a4SAndroid Build Coastguard Worker // Parses the number input and returns a tuple including the number itself (with its sign) and
180*bb4ee6a4SAndroid Build Coastguard Worker // its radix.
181*bb4ee6a4SAndroid Build Coastguard Worker //
182*bb4ee6a4SAndroid Build Coastguard Worker // We move this non-generic part into its own function so it doesn't get monomorphized, which
183*bb4ee6a4SAndroid Build Coastguard Worker // would increase the binary size more than needed.
184*bb4ee6a4SAndroid Build Coastguard Worker fn parse_number(s: &str) -> IResult<&str, (Cow<str>, u32)> {
185*bb4ee6a4SAndroid Build Coastguard Worker // Recognizes the sign prefix.
186*bb4ee6a4SAndroid Build Coastguard Worker let sign = char('-');
187*bb4ee6a4SAndroid Build Coastguard Worker
188*bb4ee6a4SAndroid Build Coastguard Worker // Recognizes the radix prefix.
189*bb4ee6a4SAndroid Build Coastguard Worker let radix = alt((
190*bb4ee6a4SAndroid Build Coastguard Worker value(16, tag("0x")),
191*bb4ee6a4SAndroid Build Coastguard Worker value(8, tag("0o")),
192*bb4ee6a4SAndroid Build Coastguard Worker value(2, tag("0b")),
193*bb4ee6a4SAndroid Build Coastguard Worker ));
194*bb4ee6a4SAndroid Build Coastguard Worker
195*bb4ee6a4SAndroid Build Coastguard Worker // Recognizes the trailing separator but do not consume it.
196*bb4ee6a4SAndroid Build Coastguard Worker let separator = peek(any_separator);
197*bb4ee6a4SAndroid Build Coastguard Worker
198*bb4ee6a4SAndroid Build Coastguard Worker // Chain of parsers: sign (optional) and radix (optional), then sequence of alphanumerical
199*bb4ee6a4SAndroid Build Coastguard Worker // characters.
200*bb4ee6a4SAndroid Build Coastguard Worker //
201*bb4ee6a4SAndroid Build Coastguard Worker // Then we take all 3 recognized elements and turn them into the string and radix to pass to
202*bb4ee6a4SAndroid Build Coastguard Worker // `from_str_radix`.
203*bb4ee6a4SAndroid Build Coastguard Worker map(
204*bb4ee6a4SAndroid Build Coastguard Worker tuple((opt(sign), opt(radix), alphanumeric1, separator)),
205*bb4ee6a4SAndroid Build Coastguard Worker |(sign, radix, number, _)| {
206*bb4ee6a4SAndroid Build Coastguard Worker // If the sign was specified, we need to build a string that contains it for
207*bb4ee6a4SAndroid Build Coastguard Worker // `from_str_radix` to parse the number accurately. Otherwise, simply borrow the
208*bb4ee6a4SAndroid Build Coastguard Worker // remainder of the input.
209*bb4ee6a4SAndroid Build Coastguard Worker let num_string = if let Some(sign) = sign {
210*bb4ee6a4SAndroid Build Coastguard Worker Cow::Owned(sign.to_string() + number)
211*bb4ee6a4SAndroid Build Coastguard Worker } else {
212*bb4ee6a4SAndroid Build Coastguard Worker Cow::Borrowed(number)
213*bb4ee6a4SAndroid Build Coastguard Worker };
214*bb4ee6a4SAndroid Build Coastguard Worker
215*bb4ee6a4SAndroid Build Coastguard Worker (num_string, radix.unwrap_or(10))
216*bb4ee6a4SAndroid Build Coastguard Worker },
217*bb4ee6a4SAndroid Build Coastguard Worker )(s)
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker
220*bb4ee6a4SAndroid Build Coastguard Worker map_res(parse_number, |(num_string, radix)| {
221*bb4ee6a4SAndroid Build Coastguard Worker T::from_str_radix(&num_string, radix)
222*bb4ee6a4SAndroid Build Coastguard Worker })(s)
223*bb4ee6a4SAndroid Build Coastguard Worker }
224*bb4ee6a4SAndroid Build Coastguard Worker
225*bb4ee6a4SAndroid Build Coastguard Worker /// Nom parser for booleans.
any_bool(s: &str) -> IResult<&str, bool>226*bb4ee6a4SAndroid Build Coastguard Worker fn any_bool(s: &str) -> IResult<&str, bool> {
227*bb4ee6a4SAndroid Build Coastguard Worker let mut boolean = alt((value(true, tag("true")), value(false, tag("false"))));
228*bb4ee6a4SAndroid Build Coastguard Worker
229*bb4ee6a4SAndroid Build Coastguard Worker boolean(s)
230*bb4ee6a4SAndroid Build Coastguard Worker }
231*bb4ee6a4SAndroid Build Coastguard Worker
232*bb4ee6a4SAndroid Build Coastguard Worker /// Nom parser for identifiers. An identifier may contain any alphanumeric character, as well as
233*bb4ee6a4SAndroid Build Coastguard Worker /// '_' and '-' at any place excepted the first one which cannot be '-'.
234*bb4ee6a4SAndroid Build Coastguard Worker ///
235*bb4ee6a4SAndroid Build Coastguard Worker /// Usually identifiers are not allowed to start with a number, but we chose to allow this
236*bb4ee6a4SAndroid Build Coastguard Worker /// here otherwise options like "mode=2d" won't parse if "2d" is an alias for an enum variant.
any_identifier(s: &str) -> IResult<&str, &str>237*bb4ee6a4SAndroid Build Coastguard Worker fn any_identifier(s: &str) -> IResult<&str, &str> {
238*bb4ee6a4SAndroid Build Coastguard Worker let mut ident = recognize(pair(
239*bb4ee6a4SAndroid Build Coastguard Worker verify(anychar, |&c| c.is_alphanum() || c == '_'),
240*bb4ee6a4SAndroid Build Coastguard Worker take_while(|c: char| c.is_alphanum() || c == '_' || c == '-'),
241*bb4ee6a4SAndroid Build Coastguard Worker ));
242*bb4ee6a4SAndroid Build Coastguard Worker
243*bb4ee6a4SAndroid Build Coastguard Worker ident(s)
244*bb4ee6a4SAndroid Build Coastguard Worker }
245*bb4ee6a4SAndroid Build Coastguard Worker
246*bb4ee6a4SAndroid Build Coastguard Worker /// Serde deserializer for key-values strings.
247*bb4ee6a4SAndroid Build Coastguard Worker pub struct KeyValueDeserializer<'de> {
248*bb4ee6a4SAndroid Build Coastguard Worker /// Full input originally received for parsing.
249*bb4ee6a4SAndroid Build Coastguard Worker original_input: &'de str,
250*bb4ee6a4SAndroid Build Coastguard Worker /// Input currently remaining to parse.
251*bb4ee6a4SAndroid Build Coastguard Worker input: &'de str,
252*bb4ee6a4SAndroid Build Coastguard Worker /// If set, then `deserialize_identifier` will take and return its content the next time it is
253*bb4ee6a4SAndroid Build Coastguard Worker /// called instead of trying to parse an identifier from the input. This is needed to allow the
254*bb4ee6a4SAndroid Build Coastguard Worker /// name of the first field of a struct to be omitted, e.g.
255*bb4ee6a4SAndroid Build Coastguard Worker ///
256*bb4ee6a4SAndroid Build Coastguard Worker /// --block "/path/to/disk.img,ro=true"
257*bb4ee6a4SAndroid Build Coastguard Worker ///
258*bb4ee6a4SAndroid Build Coastguard Worker /// instead of
259*bb4ee6a4SAndroid Build Coastguard Worker ///
260*bb4ee6a4SAndroid Build Coastguard Worker /// --block "path=/path/to/disk.img,ro=true"
261*bb4ee6a4SAndroid Build Coastguard Worker next_identifier: Option<&'de str>,
262*bb4ee6a4SAndroid Build Coastguard Worker /// Whether the '=' sign has been parsed after a key. The absence of '=' is only valid for
263*bb4ee6a4SAndroid Build Coastguard Worker /// boolean fields, in which case the field's value will be `true`.
264*bb4ee6a4SAndroid Build Coastguard Worker has_equal: bool,
265*bb4ee6a4SAndroid Build Coastguard Worker /// Whether the top structure has been parsed yet or not. The top structure is the only one
266*bb4ee6a4SAndroid Build Coastguard Worker /// that does not require to be enclosed within braces.
267*bb4ee6a4SAndroid Build Coastguard Worker top_struct_parsed: bool,
268*bb4ee6a4SAndroid Build Coastguard Worker }
269*bb4ee6a4SAndroid Build Coastguard Worker
270*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> From<&'de str> for KeyValueDeserializer<'de> {
from(input: &'de str) -> Self271*bb4ee6a4SAndroid Build Coastguard Worker fn from(input: &'de str) -> Self {
272*bb4ee6a4SAndroid Build Coastguard Worker Self {
273*bb4ee6a4SAndroid Build Coastguard Worker original_input: input,
274*bb4ee6a4SAndroid Build Coastguard Worker input,
275*bb4ee6a4SAndroid Build Coastguard Worker next_identifier: None,
276*bb4ee6a4SAndroid Build Coastguard Worker has_equal: false,
277*bb4ee6a4SAndroid Build Coastguard Worker top_struct_parsed: false,
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker }
280*bb4ee6a4SAndroid Build Coastguard Worker }
281*bb4ee6a4SAndroid Build Coastguard Worker
282*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> KeyValueDeserializer<'de> {
283*bb4ee6a4SAndroid Build Coastguard Worker /// Return an `kind` error for the current position of the input.
error_here(&self, kind: ErrorKind) -> ParseError284*bb4ee6a4SAndroid Build Coastguard Worker pub fn error_here(&self, kind: ErrorKind) -> ParseError {
285*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
286*bb4ee6a4SAndroid Build Coastguard Worker kind,
287*bb4ee6a4SAndroid Build Coastguard Worker pos: self.original_input.len() - self.input.len(),
288*bb4ee6a4SAndroid Build Coastguard Worker }
289*bb4ee6a4SAndroid Build Coastguard Worker }
290*bb4ee6a4SAndroid Build Coastguard Worker
291*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the next char in the input string without consuming it, or None
292*bb4ee6a4SAndroid Build Coastguard Worker /// if we reached the end of input.
peek_char(&self) -> Option<char>293*bb4ee6a4SAndroid Build Coastguard Worker pub fn peek_char(&self) -> Option<char> {
294*bb4ee6a4SAndroid Build Coastguard Worker self.input.chars().next()
295*bb4ee6a4SAndroid Build Coastguard Worker }
296*bb4ee6a4SAndroid Build Coastguard Worker
297*bb4ee6a4SAndroid Build Coastguard Worker /// Skip the next char in the input string.
skip_char(&mut self)298*bb4ee6a4SAndroid Build Coastguard Worker pub fn skip_char(&mut self) {
299*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.next_char();
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker
302*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the next char in the input string and consume it, or returns
303*bb4ee6a4SAndroid Build Coastguard Worker /// None if we reached the end of input.
next_char(&mut self) -> Option<char>304*bb4ee6a4SAndroid Build Coastguard Worker pub fn next_char(&mut self) -> Option<char> {
305*bb4ee6a4SAndroid Build Coastguard Worker let c = self.peek_char()?;
306*bb4ee6a4SAndroid Build Coastguard Worker self.input = &self.input[c.len_utf8()..];
307*bb4ee6a4SAndroid Build Coastguard Worker Some(c)
308*bb4ee6a4SAndroid Build Coastguard Worker }
309*bb4ee6a4SAndroid Build Coastguard Worker
310*bb4ee6a4SAndroid Build Coastguard Worker /// Confirm that we have a separator (i.e. ',' or ']') character or have reached the end of the
311*bb4ee6a4SAndroid Build Coastguard Worker /// input string.
confirm_separator(&mut self) -> Result<()>312*bb4ee6a4SAndroid Build Coastguard Worker fn confirm_separator(&mut self) -> Result<()> {
313*bb4ee6a4SAndroid Build Coastguard Worker // We must have a comma or end of input after a value.
314*bb4ee6a4SAndroid Build Coastguard Worker match self.peek_char() {
315*bb4ee6a4SAndroid Build Coastguard Worker Some(',') => {
316*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.next_char();
317*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
318*bb4ee6a4SAndroid Build Coastguard Worker }
319*bb4ee6a4SAndroid Build Coastguard Worker Some(']') | None => Ok(()),
320*bb4ee6a4SAndroid Build Coastguard Worker Some(_) => Err(self.error_here(ErrorKind::ExpectedComma)),
321*bb4ee6a4SAndroid Build Coastguard Worker }
322*bb4ee6a4SAndroid Build Coastguard Worker }
323*bb4ee6a4SAndroid Build Coastguard Worker
324*bb4ee6a4SAndroid Build Coastguard Worker /// Attempts to parse an identifier, either for a key or for the value of an enum type.
parse_identifier(&mut self) -> Result<&'de str>325*bb4ee6a4SAndroid Build Coastguard Worker pub fn parse_identifier(&mut self) -> Result<&'de str> {
326*bb4ee6a4SAndroid Build Coastguard Worker let (remainder, res) = any_identifier(self.input)
327*bb4ee6a4SAndroid Build Coastguard Worker .finish()
328*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| self.error_here(ErrorKind::ExpectedIdentifier))?;
329*bb4ee6a4SAndroid Build Coastguard Worker
330*bb4ee6a4SAndroid Build Coastguard Worker self.input = remainder;
331*bb4ee6a4SAndroid Build Coastguard Worker Ok(res)
332*bb4ee6a4SAndroid Build Coastguard Worker }
333*bb4ee6a4SAndroid Build Coastguard Worker
334*bb4ee6a4SAndroid Build Coastguard Worker /// Attempts to parse a string.
parse_string(&mut self) -> Result<Cow<'de, str>>335*bb4ee6a4SAndroid Build Coastguard Worker pub fn parse_string(&mut self) -> Result<Cow<'de, str>> {
336*bb4ee6a4SAndroid Build Coastguard Worker let (remainder, res) =
337*bb4ee6a4SAndroid Build Coastguard Worker any_string(self.input)
338*bb4ee6a4SAndroid Build Coastguard Worker .finish()
339*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e: nom::error::Error<_>| {
340*bb4ee6a4SAndroid Build Coastguard Worker self.input = e.input;
341*bb4ee6a4SAndroid Build Coastguard Worker // Any error means we did not have a well-formed string.
342*bb4ee6a4SAndroid Build Coastguard Worker self.error_here(ErrorKind::ExpectedString)
343*bb4ee6a4SAndroid Build Coastguard Worker })?;
344*bb4ee6a4SAndroid Build Coastguard Worker
345*bb4ee6a4SAndroid Build Coastguard Worker self.input = remainder;
346*bb4ee6a4SAndroid Build Coastguard Worker
347*bb4ee6a4SAndroid Build Coastguard Worker // The character following a string will be either a comma, a closing bracket, or EOS. If
348*bb4ee6a4SAndroid Build Coastguard Worker // we have something else, this means an unquoted string should probably have been quoted.
349*bb4ee6a4SAndroid Build Coastguard Worker if is_separator(self.peek_char()) {
350*bb4ee6a4SAndroid Build Coastguard Worker Ok(res)
351*bb4ee6a4SAndroid Build Coastguard Worker } else {
352*bb4ee6a4SAndroid Build Coastguard Worker Err(self.error_here(ErrorKind::InvalidCharInString))
353*bb4ee6a4SAndroid Build Coastguard Worker }
354*bb4ee6a4SAndroid Build Coastguard Worker }
355*bb4ee6a4SAndroid Build Coastguard Worker
356*bb4ee6a4SAndroid Build Coastguard Worker /// Attempt to parse a boolean.
parse_bool(&mut self) -> Result<bool>357*bb4ee6a4SAndroid Build Coastguard Worker pub fn parse_bool(&mut self) -> Result<bool> {
358*bb4ee6a4SAndroid Build Coastguard Worker let (remainder, res) =
359*bb4ee6a4SAndroid Build Coastguard Worker any_bool(self.input)
360*bb4ee6a4SAndroid Build Coastguard Worker .finish()
361*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e: nom::error::Error<_>| {
362*bb4ee6a4SAndroid Build Coastguard Worker self.input = e.input;
363*bb4ee6a4SAndroid Build Coastguard Worker self.error_here(ErrorKind::ExpectedBoolean)
364*bb4ee6a4SAndroid Build Coastguard Worker })?;
365*bb4ee6a4SAndroid Build Coastguard Worker
366*bb4ee6a4SAndroid Build Coastguard Worker self.input = remainder;
367*bb4ee6a4SAndroid Build Coastguard Worker Ok(res)
368*bb4ee6a4SAndroid Build Coastguard Worker }
369*bb4ee6a4SAndroid Build Coastguard Worker
370*bb4ee6a4SAndroid Build Coastguard Worker /// Attempt to parse a positive or negative number.
parse_number<T>(&mut self) -> Result<T> where T: Num<FromStrRadixErr = ParseIntError>,371*bb4ee6a4SAndroid Build Coastguard Worker pub fn parse_number<T>(&mut self) -> Result<T>
372*bb4ee6a4SAndroid Build Coastguard Worker where
373*bb4ee6a4SAndroid Build Coastguard Worker T: Num<FromStrRadixErr = ParseIntError>,
374*bb4ee6a4SAndroid Build Coastguard Worker {
375*bb4ee6a4SAndroid Build Coastguard Worker let (remainder, val) = any_number(self.input)
376*bb4ee6a4SAndroid Build Coastguard Worker .finish()
377*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| self.error_here(ErrorKind::InvalidNumber))?;
378*bb4ee6a4SAndroid Build Coastguard Worker
379*bb4ee6a4SAndroid Build Coastguard Worker self.input = remainder;
380*bb4ee6a4SAndroid Build Coastguard Worker Ok(val)
381*bb4ee6a4SAndroid Build Coastguard Worker }
382*bb4ee6a4SAndroid Build Coastguard Worker
383*bb4ee6a4SAndroid Build Coastguard Worker /// Consume this deserializer and return a `TrailingCharacters` error if some input was
384*bb4ee6a4SAndroid Build Coastguard Worker /// remaining.
385*bb4ee6a4SAndroid Build Coastguard Worker ///
386*bb4ee6a4SAndroid Build Coastguard Worker /// This is useful to confirm that the whole input has been consumed without any extra elements.
finish(self) -> Result<()>387*bb4ee6a4SAndroid Build Coastguard Worker pub fn finish(self) -> Result<()> {
388*bb4ee6a4SAndroid Build Coastguard Worker if self.input.is_empty() {
389*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
390*bb4ee6a4SAndroid Build Coastguard Worker } else {
391*bb4ee6a4SAndroid Build Coastguard Worker Err(self.error_here(ErrorKind::TrailingCharacters))
392*bb4ee6a4SAndroid Build Coastguard Worker }
393*bb4ee6a4SAndroid Build Coastguard Worker }
394*bb4ee6a4SAndroid Build Coastguard Worker }
395*bb4ee6a4SAndroid Build Coastguard Worker
396*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> de::MapAccess<'de> for KeyValueDeserializer<'de> {
397*bb4ee6a4SAndroid Build Coastguard Worker type Error = ParseError;
398*bb4ee6a4SAndroid Build Coastguard Worker
next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>> where K: de::DeserializeSeed<'de>,399*bb4ee6a4SAndroid Build Coastguard Worker fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
400*bb4ee6a4SAndroid Build Coastguard Worker where
401*bb4ee6a4SAndroid Build Coastguard Worker K: de::DeserializeSeed<'de>,
402*bb4ee6a4SAndroid Build Coastguard Worker {
403*bb4ee6a4SAndroid Build Coastguard Worker // Detect end of input or struct.
404*bb4ee6a4SAndroid Build Coastguard Worker match self.peek_char() {
405*bb4ee6a4SAndroid Build Coastguard Worker None | Some(']') => return Ok(None),
406*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
407*bb4ee6a4SAndroid Build Coastguard Worker }
408*bb4ee6a4SAndroid Build Coastguard Worker
409*bb4ee6a4SAndroid Build Coastguard Worker self.has_equal = false;
410*bb4ee6a4SAndroid Build Coastguard Worker
411*bb4ee6a4SAndroid Build Coastguard Worker let had_implicit_identifier = self.next_identifier.is_some();
412*bb4ee6a4SAndroid Build Coastguard Worker let val = seed.deserialize(&mut *self).map(Some)?;
413*bb4ee6a4SAndroid Build Coastguard Worker // We just "deserialized" the content of `next_identifier`, so there should be no equal
414*bb4ee6a4SAndroid Build Coastguard Worker // character in the input. We can return now.
415*bb4ee6a4SAndroid Build Coastguard Worker if had_implicit_identifier {
416*bb4ee6a4SAndroid Build Coastguard Worker self.has_equal = true;
417*bb4ee6a4SAndroid Build Coastguard Worker return Ok(val);
418*bb4ee6a4SAndroid Build Coastguard Worker }
419*bb4ee6a4SAndroid Build Coastguard Worker
420*bb4ee6a4SAndroid Build Coastguard Worker match self.peek_char() {
421*bb4ee6a4SAndroid Build Coastguard Worker // We expect an equal after an identifier.
422*bb4ee6a4SAndroid Build Coastguard Worker Some('=') => {
423*bb4ee6a4SAndroid Build Coastguard Worker self.skip_char();
424*bb4ee6a4SAndroid Build Coastguard Worker self.has_equal = true;
425*bb4ee6a4SAndroid Build Coastguard Worker Ok(val)
426*bb4ee6a4SAndroid Build Coastguard Worker }
427*bb4ee6a4SAndroid Build Coastguard Worker // Ok if we are parsing a boolean where an empty value means true.
428*bb4ee6a4SAndroid Build Coastguard Worker c if is_separator(c) => Ok(val),
429*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(self.error_here(ErrorKind::ExpectedEqual)),
430*bb4ee6a4SAndroid Build Coastguard Worker }
431*bb4ee6a4SAndroid Build Coastguard Worker }
432*bb4ee6a4SAndroid Build Coastguard Worker
next_value_seed<V>(&mut self, seed: V) -> Result<V::Value> where V: de::DeserializeSeed<'de>,433*bb4ee6a4SAndroid Build Coastguard Worker fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
434*bb4ee6a4SAndroid Build Coastguard Worker where
435*bb4ee6a4SAndroid Build Coastguard Worker V: de::DeserializeSeed<'de>,
436*bb4ee6a4SAndroid Build Coastguard Worker {
437*bb4ee6a4SAndroid Build Coastguard Worker let val = seed.deserialize(&mut *self)?;
438*bb4ee6a4SAndroid Build Coastguard Worker
439*bb4ee6a4SAndroid Build Coastguard Worker self.confirm_separator()?;
440*bb4ee6a4SAndroid Build Coastguard Worker
441*bb4ee6a4SAndroid Build Coastguard Worker Ok(val)
442*bb4ee6a4SAndroid Build Coastguard Worker }
443*bb4ee6a4SAndroid Build Coastguard Worker }
444*bb4ee6a4SAndroid Build Coastguard Worker
445*bb4ee6a4SAndroid Build Coastguard Worker /// `MapAccess` for a map with no members specified.
446*bb4ee6a4SAndroid Build Coastguard Worker ///
447*bb4ee6a4SAndroid Build Coastguard Worker /// This is used to allow a struct enum type to be specified without `[` and `]`, in which case
448*bb4ee6a4SAndroid Build Coastguard Worker /// all its members will take their default value:
449*bb4ee6a4SAndroid Build Coastguard Worker ///
450*bb4ee6a4SAndroid Build Coastguard Worker /// ```
451*bb4ee6a4SAndroid Build Coastguard Worker /// # use serde_keyvalue::from_key_values;
452*bb4ee6a4SAndroid Build Coastguard Worker /// # use serde::Deserialize;
453*bb4ee6a4SAndroid Build Coastguard Worker /// #[derive(Deserialize, PartialEq, Eq, Debug)]
454*bb4ee6a4SAndroid Build Coastguard Worker /// #[serde(rename_all = "kebab-case")]
455*bb4ee6a4SAndroid Build Coastguard Worker /// enum FlipMode {
456*bb4ee6a4SAndroid Build Coastguard Worker /// Active {
457*bb4ee6a4SAndroid Build Coastguard Worker /// #[serde(default)]
458*bb4ee6a4SAndroid Build Coastguard Worker /// switch1: bool,
459*bb4ee6a4SAndroid Build Coastguard Worker /// #[serde(default)]
460*bb4ee6a4SAndroid Build Coastguard Worker /// switch2: bool,
461*bb4ee6a4SAndroid Build Coastguard Worker /// },
462*bb4ee6a4SAndroid Build Coastguard Worker /// }
463*bb4ee6a4SAndroid Build Coastguard Worker /// #[derive(Deserialize, PartialEq, Eq, Debug)]
464*bb4ee6a4SAndroid Build Coastguard Worker /// struct TestStruct {
465*bb4ee6a4SAndroid Build Coastguard Worker /// mode: FlipMode,
466*bb4ee6a4SAndroid Build Coastguard Worker /// }
467*bb4ee6a4SAndroid Build Coastguard Worker /// let res: TestStruct = from_key_values("mode=active").unwrap();
468*bb4ee6a4SAndroid Build Coastguard Worker /// assert_eq!(
469*bb4ee6a4SAndroid Build Coastguard Worker /// res,
470*bb4ee6a4SAndroid Build Coastguard Worker /// TestStruct {
471*bb4ee6a4SAndroid Build Coastguard Worker /// mode: FlipMode::Active {
472*bb4ee6a4SAndroid Build Coastguard Worker /// switch1: false,
473*bb4ee6a4SAndroid Build Coastguard Worker /// switch2: false
474*bb4ee6a4SAndroid Build Coastguard Worker /// }
475*bb4ee6a4SAndroid Build Coastguard Worker /// }
476*bb4ee6a4SAndroid Build Coastguard Worker /// );
477*bb4ee6a4SAndroid Build Coastguard Worker /// ```
478*bb4ee6a4SAndroid Build Coastguard Worker struct EmptyMapAccess;
479*bb4ee6a4SAndroid Build Coastguard Worker
480*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> de::MapAccess<'de> for EmptyMapAccess {
481*bb4ee6a4SAndroid Build Coastguard Worker type Error = ParseError;
482*bb4ee6a4SAndroid Build Coastguard Worker
next_key_seed<K>(&mut self, _seed: K) -> Result<Option<K::Value>> where K: de::DeserializeSeed<'de>,483*bb4ee6a4SAndroid Build Coastguard Worker fn next_key_seed<K>(&mut self, _seed: K) -> Result<Option<K::Value>>
484*bb4ee6a4SAndroid Build Coastguard Worker where
485*bb4ee6a4SAndroid Build Coastguard Worker K: de::DeserializeSeed<'de>,
486*bb4ee6a4SAndroid Build Coastguard Worker {
487*bb4ee6a4SAndroid Build Coastguard Worker Ok(None)
488*bb4ee6a4SAndroid Build Coastguard Worker }
489*bb4ee6a4SAndroid Build Coastguard Worker
next_value_seed<V>(&mut self, _seed: V) -> Result<V::Value> where V: de::DeserializeSeed<'de>,490*bb4ee6a4SAndroid Build Coastguard Worker fn next_value_seed<V>(&mut self, _seed: V) -> Result<V::Value>
491*bb4ee6a4SAndroid Build Coastguard Worker where
492*bb4ee6a4SAndroid Build Coastguard Worker V: de::DeserializeSeed<'de>,
493*bb4ee6a4SAndroid Build Coastguard Worker {
494*bb4ee6a4SAndroid Build Coastguard Worker // Never reached because `next_key_seed` never returns a valid key.
495*bb4ee6a4SAndroid Build Coastguard Worker unreachable!()
496*bb4ee6a4SAndroid Build Coastguard Worker }
497*bb4ee6a4SAndroid Build Coastguard Worker }
498*bb4ee6a4SAndroid Build Coastguard Worker
499*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, 'de> de::EnumAccess<'de> for &'a mut KeyValueDeserializer<'de> {
500*bb4ee6a4SAndroid Build Coastguard Worker type Error = ParseError;
501*bb4ee6a4SAndroid Build Coastguard Worker type Variant = Self;
502*bb4ee6a4SAndroid Build Coastguard Worker
variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: de::DeserializeSeed<'de>,503*bb4ee6a4SAndroid Build Coastguard Worker fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
504*bb4ee6a4SAndroid Build Coastguard Worker where
505*bb4ee6a4SAndroid Build Coastguard Worker V: de::DeserializeSeed<'de>,
506*bb4ee6a4SAndroid Build Coastguard Worker {
507*bb4ee6a4SAndroid Build Coastguard Worker let val = seed.deserialize(&mut *self)?;
508*bb4ee6a4SAndroid Build Coastguard Worker Ok((val, self))
509*bb4ee6a4SAndroid Build Coastguard Worker }
510*bb4ee6a4SAndroid Build Coastguard Worker }
511*bb4ee6a4SAndroid Build Coastguard Worker
512*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, 'de> de::VariantAccess<'de> for &'a mut KeyValueDeserializer<'de> {
513*bb4ee6a4SAndroid Build Coastguard Worker type Error = ParseError;
514*bb4ee6a4SAndroid Build Coastguard Worker
unit_variant(self) -> Result<()>515*bb4ee6a4SAndroid Build Coastguard Worker fn unit_variant(self) -> Result<()> {
516*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
517*bb4ee6a4SAndroid Build Coastguard Worker }
518*bb4ee6a4SAndroid Build Coastguard Worker
newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value> where T: de::DeserializeSeed<'de>,519*bb4ee6a4SAndroid Build Coastguard Worker fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value>
520*bb4ee6a4SAndroid Build Coastguard Worker where
521*bb4ee6a4SAndroid Build Coastguard Worker T: de::DeserializeSeed<'de>,
522*bb4ee6a4SAndroid Build Coastguard Worker {
523*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
524*bb4ee6a4SAndroid Build Coastguard Worker }
525*bb4ee6a4SAndroid Build Coastguard Worker
tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>,526*bb4ee6a4SAndroid Build Coastguard Worker fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
527*bb4ee6a4SAndroid Build Coastguard Worker where
528*bb4ee6a4SAndroid Build Coastguard Worker V: de::Visitor<'de>,
529*bb4ee6a4SAndroid Build Coastguard Worker {
530*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_tuple(len, visitor)
531*bb4ee6a4SAndroid Build Coastguard Worker }
532*bb4ee6a4SAndroid Build Coastguard Worker
struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value> where V: de::Visitor<'de>,533*bb4ee6a4SAndroid Build Coastguard Worker fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
534*bb4ee6a4SAndroid Build Coastguard Worker where
535*bb4ee6a4SAndroid Build Coastguard Worker V: de::Visitor<'de>,
536*bb4ee6a4SAndroid Build Coastguard Worker {
537*bb4ee6a4SAndroid Build Coastguard Worker if self.peek_char() == Some('[') {
538*bb4ee6a4SAndroid Build Coastguard Worker self.next_char();
539*bb4ee6a4SAndroid Build Coastguard Worker let val = self.deserialize_map(visitor)?;
540*bb4ee6a4SAndroid Build Coastguard Worker
541*bb4ee6a4SAndroid Build Coastguard Worker if self.peek_char() != Some(']') {
542*bb4ee6a4SAndroid Build Coastguard Worker Err(self.error_here(ErrorKind::ExpectedCloseBracket))
543*bb4ee6a4SAndroid Build Coastguard Worker } else {
544*bb4ee6a4SAndroid Build Coastguard Worker self.next_char();
545*bb4ee6a4SAndroid Build Coastguard Worker Ok(val)
546*bb4ee6a4SAndroid Build Coastguard Worker }
547*bb4ee6a4SAndroid Build Coastguard Worker } else {
548*bb4ee6a4SAndroid Build Coastguard Worker // The `EmptyMapAccess` failing to parse means that this enum must take arguments, i.e.
549*bb4ee6a4SAndroid Build Coastguard Worker // that an opening bracket is expected.
550*bb4ee6a4SAndroid Build Coastguard Worker visitor
551*bb4ee6a4SAndroid Build Coastguard Worker .visit_map(EmptyMapAccess)
552*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| self.error_here(ErrorKind::ExpectedOpenBracket))
553*bb4ee6a4SAndroid Build Coastguard Worker }
554*bb4ee6a4SAndroid Build Coastguard Worker }
555*bb4ee6a4SAndroid Build Coastguard Worker }
556*bb4ee6a4SAndroid Build Coastguard Worker
557*bb4ee6a4SAndroid Build Coastguard Worker impl<'de> de::SeqAccess<'de> for KeyValueDeserializer<'de> {
558*bb4ee6a4SAndroid Build Coastguard Worker type Error = ParseError;
559*bb4ee6a4SAndroid Build Coastguard Worker
next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>> where T: de::DeserializeSeed<'de>,560*bb4ee6a4SAndroid Build Coastguard Worker fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
561*bb4ee6a4SAndroid Build Coastguard Worker where
562*bb4ee6a4SAndroid Build Coastguard Worker T: de::DeserializeSeed<'de>,
563*bb4ee6a4SAndroid Build Coastguard Worker {
564*bb4ee6a4SAndroid Build Coastguard Worker if self.peek_char() == Some(']') {
565*bb4ee6a4SAndroid Build Coastguard Worker return Ok(None);
566*bb4ee6a4SAndroid Build Coastguard Worker }
567*bb4ee6a4SAndroid Build Coastguard Worker
568*bb4ee6a4SAndroid Build Coastguard Worker let value = seed.deserialize(&mut *self)?;
569*bb4ee6a4SAndroid Build Coastguard Worker
570*bb4ee6a4SAndroid Build Coastguard Worker self.confirm_separator()?;
571*bb4ee6a4SAndroid Build Coastguard Worker
572*bb4ee6a4SAndroid Build Coastguard Worker Ok(Some(value))
573*bb4ee6a4SAndroid Build Coastguard Worker }
574*bb4ee6a4SAndroid Build Coastguard Worker }
575*bb4ee6a4SAndroid Build Coastguard Worker
576*bb4ee6a4SAndroid Build Coastguard Worker impl<'de, 'a> de::Deserializer<'de> for &'a mut KeyValueDeserializer<'de> {
577*bb4ee6a4SAndroid Build Coastguard Worker type Error = ParseError;
578*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_any<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,579*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
580*bb4ee6a4SAndroid Build Coastguard Worker where
581*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
582*bb4ee6a4SAndroid Build Coastguard Worker {
583*bb4ee6a4SAndroid Build Coastguard Worker match self.peek_char() {
584*bb4ee6a4SAndroid Build Coastguard Worker // If we have no value following, then we are dealing with a boolean flag.
585*bb4ee6a4SAndroid Build Coastguard Worker c if is_separator(c) => return self.deserialize_bool(visitor),
586*bb4ee6a4SAndroid Build Coastguard Worker // Opening bracket means we have a sequence.
587*bb4ee6a4SAndroid Build Coastguard Worker Some('[') => return self.deserialize_seq(visitor),
588*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
589*bb4ee6a4SAndroid Build Coastguard Worker }
590*bb4ee6a4SAndroid Build Coastguard Worker
591*bb4ee6a4SAndroid Build Coastguard Worker // This is ambiguous as technically any argument could be an unquoted string. However we
592*bb4ee6a4SAndroid Build Coastguard Worker // don't have any type information here, so try to guess it on a best-effort basis...
593*bb4ee6a4SAndroid Build Coastguard Worker if any_number::<i64>(self.input).is_ok() {
594*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_i64(visitor)
595*bb4ee6a4SAndroid Build Coastguard Worker } else if any_number::<u64>(self.input).is_ok() {
596*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_u64(visitor)
597*bb4ee6a4SAndroid Build Coastguard Worker } else if any_bool(self.input).is_ok() {
598*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_bool(visitor)
599*bb4ee6a4SAndroid Build Coastguard Worker } else {
600*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_str(visitor)
601*bb4ee6a4SAndroid Build Coastguard Worker }
602*bb4ee6a4SAndroid Build Coastguard Worker }
603*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_bool<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,604*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
605*bb4ee6a4SAndroid Build Coastguard Worker where
606*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
607*bb4ee6a4SAndroid Build Coastguard Worker {
608*bb4ee6a4SAndroid Build Coastguard Worker // It is valid to just mention a bool as a flag and not specify its value - in this case
609*bb4ee6a4SAndroid Build Coastguard Worker // the value is set as `true`.
610*bb4ee6a4SAndroid Build Coastguard Worker let val = if self.has_equal {
611*bb4ee6a4SAndroid Build Coastguard Worker self.parse_bool()?
612*bb4ee6a4SAndroid Build Coastguard Worker } else {
613*bb4ee6a4SAndroid Build Coastguard Worker true
614*bb4ee6a4SAndroid Build Coastguard Worker };
615*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_bool(val)
616*bb4ee6a4SAndroid Build Coastguard Worker }
617*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_i8<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,618*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
619*bb4ee6a4SAndroid Build Coastguard Worker where
620*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
621*bb4ee6a4SAndroid Build Coastguard Worker {
622*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_i8(self.parse_number()?)
623*bb4ee6a4SAndroid Build Coastguard Worker }
624*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_i16<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,625*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
626*bb4ee6a4SAndroid Build Coastguard Worker where
627*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
628*bb4ee6a4SAndroid Build Coastguard Worker {
629*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_i16(self.parse_number()?)
630*bb4ee6a4SAndroid Build Coastguard Worker }
631*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_i32<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,632*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
633*bb4ee6a4SAndroid Build Coastguard Worker where
634*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
635*bb4ee6a4SAndroid Build Coastguard Worker {
636*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_i32(self.parse_number()?)
637*bb4ee6a4SAndroid Build Coastguard Worker }
638*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_i64<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,639*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
640*bb4ee6a4SAndroid Build Coastguard Worker where
641*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
642*bb4ee6a4SAndroid Build Coastguard Worker {
643*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_i64(self.parse_number()?)
644*bb4ee6a4SAndroid Build Coastguard Worker }
645*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_u8<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,646*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
647*bb4ee6a4SAndroid Build Coastguard Worker where
648*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
649*bb4ee6a4SAndroid Build Coastguard Worker {
650*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_u8(self.parse_number()?)
651*bb4ee6a4SAndroid Build Coastguard Worker }
652*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_u16<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,653*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
654*bb4ee6a4SAndroid Build Coastguard Worker where
655*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
656*bb4ee6a4SAndroid Build Coastguard Worker {
657*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_u16(self.parse_number()?)
658*bb4ee6a4SAndroid Build Coastguard Worker }
659*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_u32<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,660*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
661*bb4ee6a4SAndroid Build Coastguard Worker where
662*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
663*bb4ee6a4SAndroid Build Coastguard Worker {
664*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_u32(self.parse_number()?)
665*bb4ee6a4SAndroid Build Coastguard Worker }
666*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_u64<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,667*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
668*bb4ee6a4SAndroid Build Coastguard Worker where
669*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
670*bb4ee6a4SAndroid Build Coastguard Worker {
671*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_u64(self.parse_number()?)
672*bb4ee6a4SAndroid Build Coastguard Worker }
673*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_f32<V>(self, _visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,674*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value>
675*bb4ee6a4SAndroid Build Coastguard Worker where
676*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
677*bb4ee6a4SAndroid Build Coastguard Worker {
678*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
679*bb4ee6a4SAndroid Build Coastguard Worker }
680*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_f64<V>(self, _visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,681*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value>
682*bb4ee6a4SAndroid Build Coastguard Worker where
683*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
684*bb4ee6a4SAndroid Build Coastguard Worker {
685*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
686*bb4ee6a4SAndroid Build Coastguard Worker }
687*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_char<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,688*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
689*bb4ee6a4SAndroid Build Coastguard Worker where
690*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
691*bb4ee6a4SAndroid Build Coastguard Worker {
692*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_char(
693*bb4ee6a4SAndroid Build Coastguard Worker self.next_char()
694*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| self.error_here(ErrorKind::Eof))?,
695*bb4ee6a4SAndroid Build Coastguard Worker )
696*bb4ee6a4SAndroid Build Coastguard Worker }
697*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_str<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,698*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
699*bb4ee6a4SAndroid Build Coastguard Worker where
700*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
701*bb4ee6a4SAndroid Build Coastguard Worker {
702*bb4ee6a4SAndroid Build Coastguard Worker match self.parse_string()? {
703*bb4ee6a4SAndroid Build Coastguard Worker Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
704*bb4ee6a4SAndroid Build Coastguard Worker Cow::Owned(s) => visitor.visit_string(s),
705*bb4ee6a4SAndroid Build Coastguard Worker }
706*bb4ee6a4SAndroid Build Coastguard Worker }
707*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_string<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,708*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
709*bb4ee6a4SAndroid Build Coastguard Worker where
710*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
711*bb4ee6a4SAndroid Build Coastguard Worker {
712*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_str(visitor)
713*bb4ee6a4SAndroid Build Coastguard Worker }
714*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,715*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
716*bb4ee6a4SAndroid Build Coastguard Worker where
717*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
718*bb4ee6a4SAndroid Build Coastguard Worker {
719*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
720*bb4ee6a4SAndroid Build Coastguard Worker }
721*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,722*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
723*bb4ee6a4SAndroid Build Coastguard Worker where
724*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
725*bb4ee6a4SAndroid Build Coastguard Worker {
726*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_bytes(visitor)
727*bb4ee6a4SAndroid Build Coastguard Worker }
728*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_option<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,729*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
730*bb4ee6a4SAndroid Build Coastguard Worker where
731*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
732*bb4ee6a4SAndroid Build Coastguard Worker {
733*bb4ee6a4SAndroid Build Coastguard Worker // The fact that an option is specified implies that is exists, hence we always visit
734*bb4ee6a4SAndroid Build Coastguard Worker // Some() here.
735*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_some(self)
736*bb4ee6a4SAndroid Build Coastguard Worker }
737*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_unit<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,738*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
739*bb4ee6a4SAndroid Build Coastguard Worker where
740*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
741*bb4ee6a4SAndroid Build Coastguard Worker {
742*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_unit()
743*bb4ee6a4SAndroid Build Coastguard Worker }
744*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,745*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
746*bb4ee6a4SAndroid Build Coastguard Worker where
747*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
748*bb4ee6a4SAndroid Build Coastguard Worker {
749*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_unit(visitor)
750*bb4ee6a4SAndroid Build Coastguard Worker }
751*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,752*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
753*bb4ee6a4SAndroid Build Coastguard Worker where
754*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
755*bb4ee6a4SAndroid Build Coastguard Worker {
756*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_newtype_struct(self)
757*bb4ee6a4SAndroid Build Coastguard Worker }
758*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_seq<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,759*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
760*bb4ee6a4SAndroid Build Coastguard Worker where
761*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
762*bb4ee6a4SAndroid Build Coastguard Worker {
763*bb4ee6a4SAndroid Build Coastguard Worker if self.peek_char() == Some('[') {
764*bb4ee6a4SAndroid Build Coastguard Worker self.next_char();
765*bb4ee6a4SAndroid Build Coastguard Worker let val = visitor.visit_seq(&mut *self)?;
766*bb4ee6a4SAndroid Build Coastguard Worker
767*bb4ee6a4SAndroid Build Coastguard Worker if self.peek_char() != Some(']') {
768*bb4ee6a4SAndroid Build Coastguard Worker Err(self.error_here(ErrorKind::ExpectedCloseBracket))
769*bb4ee6a4SAndroid Build Coastguard Worker } else {
770*bb4ee6a4SAndroid Build Coastguard Worker self.next_char();
771*bb4ee6a4SAndroid Build Coastguard Worker Ok(val)
772*bb4ee6a4SAndroid Build Coastguard Worker }
773*bb4ee6a4SAndroid Build Coastguard Worker } else {
774*bb4ee6a4SAndroid Build Coastguard Worker // The `EmptyMapAccess` failing to parse means that this sequence must take arguments,
775*bb4ee6a4SAndroid Build Coastguard Worker // i.e. that an opening bracket is expected.
776*bb4ee6a4SAndroid Build Coastguard Worker visitor
777*bb4ee6a4SAndroid Build Coastguard Worker .visit_map(EmptyMapAccess)
778*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| self.error_here(ErrorKind::ExpectedOpenBracket))
779*bb4ee6a4SAndroid Build Coastguard Worker }
780*bb4ee6a4SAndroid Build Coastguard Worker }
781*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,782*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
783*bb4ee6a4SAndroid Build Coastguard Worker where
784*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
785*bb4ee6a4SAndroid Build Coastguard Worker {
786*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_seq(visitor)
787*bb4ee6a4SAndroid Build Coastguard Worker }
788*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_tuple_struct<V>( self, _name: &'static str, _len: usize, _visitor: V, ) -> Result<V::Value> where V: serde::de::Visitor<'de>,789*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_tuple_struct<V>(
790*bb4ee6a4SAndroid Build Coastguard Worker self,
791*bb4ee6a4SAndroid Build Coastguard Worker _name: &'static str,
792*bb4ee6a4SAndroid Build Coastguard Worker _len: usize,
793*bb4ee6a4SAndroid Build Coastguard Worker _visitor: V,
794*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<V::Value>
795*bb4ee6a4SAndroid Build Coastguard Worker where
796*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
797*bb4ee6a4SAndroid Build Coastguard Worker {
798*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!()
799*bb4ee6a4SAndroid Build Coastguard Worker }
800*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_map<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,801*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
802*bb4ee6a4SAndroid Build Coastguard Worker where
803*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
804*bb4ee6a4SAndroid Build Coastguard Worker {
805*bb4ee6a4SAndroid Build Coastguard Worker // The top structure (i.e. the first structure that we will ever parse) does not need to be
806*bb4ee6a4SAndroid Build Coastguard Worker // enclosed in braces, but inner structures do.
807*bb4ee6a4SAndroid Build Coastguard Worker //
808*bb4ee6a4SAndroid Build Coastguard Worker // We need to do this here as well as in `deserialize_struct` because the top-element of
809*bb4ee6a4SAndroid Build Coastguard Worker // flattened structs will be a map, not a struct.
810*bb4ee6a4SAndroid Build Coastguard Worker self.top_struct_parsed = true;
811*bb4ee6a4SAndroid Build Coastguard Worker
812*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_map(self)
813*bb4ee6a4SAndroid Build Coastguard Worker }
814*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_struct<V>( self, _name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result<V::Value> where V: serde::de::Visitor<'de>,815*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_struct<V>(
816*bb4ee6a4SAndroid Build Coastguard Worker self,
817*bb4ee6a4SAndroid Build Coastguard Worker _name: &'static str,
818*bb4ee6a4SAndroid Build Coastguard Worker fields: &'static [&'static str],
819*bb4ee6a4SAndroid Build Coastguard Worker visitor: V,
820*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<V::Value>
821*bb4ee6a4SAndroid Build Coastguard Worker where
822*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
823*bb4ee6a4SAndroid Build Coastguard Worker {
824*bb4ee6a4SAndroid Build Coastguard Worker // The top structure (i.e. the first structure that we will ever parse) does not need to be
825*bb4ee6a4SAndroid Build Coastguard Worker // enclosed in braces, but inner structures do.
826*bb4ee6a4SAndroid Build Coastguard Worker let top_struct_parsed = std::mem::replace(&mut self.top_struct_parsed, true);
827*bb4ee6a4SAndroid Build Coastguard Worker
828*bb4ee6a4SAndroid Build Coastguard Worker if top_struct_parsed {
829*bb4ee6a4SAndroid Build Coastguard Worker if self.peek_char() == Some('[') {
830*bb4ee6a4SAndroid Build Coastguard Worker self.next_char();
831*bb4ee6a4SAndroid Build Coastguard Worker } else {
832*bb4ee6a4SAndroid Build Coastguard Worker // The `EmptyMapAccess` failing to parse means that this struct must take
833*bb4ee6a4SAndroid Build Coastguard Worker // arguments, i.e. that an opening bracket is expected.
834*bb4ee6a4SAndroid Build Coastguard Worker return visitor
835*bb4ee6a4SAndroid Build Coastguard Worker .visit_map(EmptyMapAccess)
836*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| self.error_here(ErrorKind::ExpectedOpenBracket));
837*bb4ee6a4SAndroid Build Coastguard Worker }
838*bb4ee6a4SAndroid Build Coastguard Worker }
839*bb4ee6a4SAndroid Build Coastguard Worker
840*bb4ee6a4SAndroid Build Coastguard Worker // The name of the first field of a struct can be omitted (see documentation of
841*bb4ee6a4SAndroid Build Coastguard Worker // `next_identifier` for details).
842*bb4ee6a4SAndroid Build Coastguard Worker //
843*bb4ee6a4SAndroid Build Coastguard Worker // To detect this, peek the next identifier, and check if the character following is '='. If
844*bb4ee6a4SAndroid Build Coastguard Worker // it is not, then we may have a value in first position, unless the value is identical to
845*bb4ee6a4SAndroid Build Coastguard Worker // one of the field's name - in this case, assume this is a boolean using the flag syntax.
846*bb4ee6a4SAndroid Build Coastguard Worker self.next_identifier = match any_identifier(self.input) {
847*bb4ee6a4SAndroid Build Coastguard Worker Ok((_, s)) => match self.input.chars().nth(s.chars().count()) {
848*bb4ee6a4SAndroid Build Coastguard Worker Some('=') => None,
849*bb4ee6a4SAndroid Build Coastguard Worker _ => {
850*bb4ee6a4SAndroid Build Coastguard Worker if fields.contains(&s) {
851*bb4ee6a4SAndroid Build Coastguard Worker None
852*bb4ee6a4SAndroid Build Coastguard Worker } else {
853*bb4ee6a4SAndroid Build Coastguard Worker fields.first().copied()
854*bb4ee6a4SAndroid Build Coastguard Worker }
855*bb4ee6a4SAndroid Build Coastguard Worker }
856*bb4ee6a4SAndroid Build Coastguard Worker },
857*bb4ee6a4SAndroid Build Coastguard Worker // Not an identifier, probably means this is a value for the first field then.
858*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => fields.first().copied(),
859*bb4ee6a4SAndroid Build Coastguard Worker };
860*bb4ee6a4SAndroid Build Coastguard Worker
861*bb4ee6a4SAndroid Build Coastguard Worker let ret = visitor.visit_map(&mut *self)?;
862*bb4ee6a4SAndroid Build Coastguard Worker
863*bb4ee6a4SAndroid Build Coastguard Worker if top_struct_parsed {
864*bb4ee6a4SAndroid Build Coastguard Worker if self.peek_char() == Some(']') {
865*bb4ee6a4SAndroid Build Coastguard Worker self.next_char();
866*bb4ee6a4SAndroid Build Coastguard Worker } else {
867*bb4ee6a4SAndroid Build Coastguard Worker return Err(self.error_here(ErrorKind::ExpectedCloseBracket));
868*bb4ee6a4SAndroid Build Coastguard Worker }
869*bb4ee6a4SAndroid Build Coastguard Worker }
870*bb4ee6a4SAndroid Build Coastguard Worker
871*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret)
872*bb4ee6a4SAndroid Build Coastguard Worker }
873*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_enum<V>( self, _name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result<V::Value> where V: serde::de::Visitor<'de>,874*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_enum<V>(
875*bb4ee6a4SAndroid Build Coastguard Worker self,
876*bb4ee6a4SAndroid Build Coastguard Worker _name: &'static str,
877*bb4ee6a4SAndroid Build Coastguard Worker _variants: &'static [&'static str],
878*bb4ee6a4SAndroid Build Coastguard Worker visitor: V,
879*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<V::Value>
880*bb4ee6a4SAndroid Build Coastguard Worker where
881*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
882*bb4ee6a4SAndroid Build Coastguard Worker {
883*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_enum(self)
884*bb4ee6a4SAndroid Build Coastguard Worker }
885*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_identifier<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,886*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
887*bb4ee6a4SAndroid Build Coastguard Worker where
888*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
889*bb4ee6a4SAndroid Build Coastguard Worker {
890*bb4ee6a4SAndroid Build Coastguard Worker let identifier = self
891*bb4ee6a4SAndroid Build Coastguard Worker .next_identifier
892*bb4ee6a4SAndroid Build Coastguard Worker .take()
893*bb4ee6a4SAndroid Build Coastguard Worker .map_or_else(|| self.parse_identifier(), Ok)?;
894*bb4ee6a4SAndroid Build Coastguard Worker
895*bb4ee6a4SAndroid Build Coastguard Worker visitor.visit_borrowed_str(identifier)
896*bb4ee6a4SAndroid Build Coastguard Worker }
897*bb4ee6a4SAndroid Build Coastguard Worker
deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value> where V: serde::de::Visitor<'de>,898*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
899*bb4ee6a4SAndroid Build Coastguard Worker where
900*bb4ee6a4SAndroid Build Coastguard Worker V: serde::de::Visitor<'de>,
901*bb4ee6a4SAndroid Build Coastguard Worker {
902*bb4ee6a4SAndroid Build Coastguard Worker self.deserialize_any(visitor)
903*bb4ee6a4SAndroid Build Coastguard Worker }
904*bb4ee6a4SAndroid Build Coastguard Worker }
905*bb4ee6a4SAndroid Build Coastguard Worker
906*bb4ee6a4SAndroid Build Coastguard Worker /// Attempts to deserialize `T` from the key-values string `input`.
from_key_values<'a, T>(input: &'a str) -> Result<T> where T: Deserialize<'a>,907*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_key_values<'a, T>(input: &'a str) -> Result<T>
908*bb4ee6a4SAndroid Build Coastguard Worker where
909*bb4ee6a4SAndroid Build Coastguard Worker T: Deserialize<'a>,
910*bb4ee6a4SAndroid Build Coastguard Worker {
911*bb4ee6a4SAndroid Build Coastguard Worker let mut deserializer = KeyValueDeserializer::from(input);
912*bb4ee6a4SAndroid Build Coastguard Worker let ret = T::deserialize(&mut deserializer)?;
913*bb4ee6a4SAndroid Build Coastguard Worker deserializer.finish()?;
914*bb4ee6a4SAndroid Build Coastguard Worker
915*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret)
916*bb4ee6a4SAndroid Build Coastguard Worker }
917*bb4ee6a4SAndroid Build Coastguard Worker
918*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
919*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
920*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeSet;
921*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
922*bb4ee6a4SAndroid Build Coastguard Worker
923*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
924*bb4ee6a4SAndroid Build Coastguard Worker
925*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
926*bb4ee6a4SAndroid Build Coastguard Worker struct SingleStruct<T> {
927*bb4ee6a4SAndroid Build Coastguard Worker m: T,
928*bb4ee6a4SAndroid Build Coastguard Worker }
929*bb4ee6a4SAndroid Build Coastguard Worker
930*bb4ee6a4SAndroid Build Coastguard Worker #[test]
nom_any_separator()931*bb4ee6a4SAndroid Build Coastguard Worker fn nom_any_separator() {
932*bb4ee6a4SAndroid Build Coastguard Worker let test_str = ",foo";
933*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(any_separator(test_str), Ok((&test_str[1..], Some(','))));
934*bb4ee6a4SAndroid Build Coastguard Worker let test_str = "]bar";
935*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(any_separator(test_str), Ok((&test_str[1..], Some(']'))));
936*bb4ee6a4SAndroid Build Coastguard Worker let test_str = "";
937*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(any_separator(test_str), Ok((test_str, None)));
938*bb4ee6a4SAndroid Build Coastguard Worker
939*bb4ee6a4SAndroid Build Coastguard Worker let test_str = "something,anything";
940*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
941*bb4ee6a4SAndroid Build Coastguard Worker any_separator(test_str),
942*bb4ee6a4SAndroid Build Coastguard Worker Err(nom::Err::Error(nom::error::Error::new(
943*bb4ee6a4SAndroid Build Coastguard Worker test_str,
944*bb4ee6a4SAndroid Build Coastguard Worker nom::error::ErrorKind::Char
945*bb4ee6a4SAndroid Build Coastguard Worker )))
946*bb4ee6a4SAndroid Build Coastguard Worker );
947*bb4ee6a4SAndroid Build Coastguard Worker }
948*bb4ee6a4SAndroid Build Coastguard Worker
949*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_number()950*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_number() {
951*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<usize>>("m=54").unwrap();
952*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, 54);
953*bb4ee6a4SAndroid Build Coastguard Worker
954*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<isize>>("m=-54").unwrap();
955*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, -54);
956*bb4ee6a4SAndroid Build Coastguard Worker
957*bb4ee6a4SAndroid Build Coastguard Worker // Parsing a signed into an unsigned?
958*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<u32>>("m=-54").unwrap_err();
959*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
960*bb4ee6a4SAndroid Build Coastguard Worker res,
961*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
962*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidNumber,
963*bb4ee6a4SAndroid Build Coastguard Worker pos: 2
964*bb4ee6a4SAndroid Build Coastguard Worker }
965*bb4ee6a4SAndroid Build Coastguard Worker );
966*bb4ee6a4SAndroid Build Coastguard Worker
967*bb4ee6a4SAndroid Build Coastguard Worker // Value too big for a signed?
968*bb4ee6a4SAndroid Build Coastguard Worker let val = i32::MAX as u32 + 1;
969*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<i32>>(&format!("m={}", val)).unwrap_err();
970*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
971*bb4ee6a4SAndroid Build Coastguard Worker res,
972*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
973*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidNumber,
974*bb4ee6a4SAndroid Build Coastguard Worker pos: 2
975*bb4ee6a4SAndroid Build Coastguard Worker }
976*bb4ee6a4SAndroid Build Coastguard Worker );
977*bb4ee6a4SAndroid Build Coastguard Worker
978*bb4ee6a4SAndroid Build Coastguard Worker // Not a number.
979*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<usize>>("m=test").unwrap_err();
980*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
981*bb4ee6a4SAndroid Build Coastguard Worker res,
982*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
983*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidNumber,
984*bb4ee6a4SAndroid Build Coastguard Worker pos: 2,
985*bb4ee6a4SAndroid Build Coastguard Worker }
986*bb4ee6a4SAndroid Build Coastguard Worker );
987*bb4ee6a4SAndroid Build Coastguard Worker
988*bb4ee6a4SAndroid Build Coastguard Worker // Parsing hex values
989*bb4ee6a4SAndroid Build Coastguard Worker let res: SingleStruct<usize> =
990*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<SingleStruct<usize>>("m=0x1234abcd").unwrap();
991*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, 0x1234abcd);
992*bb4ee6a4SAndroid Build Coastguard Worker let res: SingleStruct<isize> =
993*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<SingleStruct<isize>>("m=-0x1234abcd").unwrap();
994*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, -0x1234abcd);
995*bb4ee6a4SAndroid Build Coastguard Worker
996*bb4ee6a4SAndroid Build Coastguard Worker // Hex value outside range
997*bb4ee6a4SAndroid Build Coastguard Worker let res: ParseError = from_key_values::<SingleStruct<usize>>("m=0xg").unwrap_err();
998*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
999*bb4ee6a4SAndroid Build Coastguard Worker res,
1000*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1001*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidNumber,
1002*bb4ee6a4SAndroid Build Coastguard Worker pos: 2,
1003*bb4ee6a4SAndroid Build Coastguard Worker }
1004*bb4ee6a4SAndroid Build Coastguard Worker );
1005*bb4ee6a4SAndroid Build Coastguard Worker
1006*bb4ee6a4SAndroid Build Coastguard Worker // Parsing octal values
1007*bb4ee6a4SAndroid Build Coastguard Worker let res: SingleStruct<usize> = from_key_values::<SingleStruct<usize>>("m=0o755").unwrap();
1008*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, 0o755);
1009*bb4ee6a4SAndroid Build Coastguard Worker let res: SingleStruct<isize> = from_key_values::<SingleStruct<isize>>("m=-0o755").unwrap();
1010*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, -0o755);
1011*bb4ee6a4SAndroid Build Coastguard Worker
1012*bb4ee6a4SAndroid Build Coastguard Worker // Octal value outside range
1013*bb4ee6a4SAndroid Build Coastguard Worker let res: ParseError = from_key_values::<SingleStruct<usize>>("m=0o8").unwrap_err();
1014*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1015*bb4ee6a4SAndroid Build Coastguard Worker res,
1016*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1017*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidNumber,
1018*bb4ee6a4SAndroid Build Coastguard Worker pos: 2,
1019*bb4ee6a4SAndroid Build Coastguard Worker }
1020*bb4ee6a4SAndroid Build Coastguard Worker );
1021*bb4ee6a4SAndroid Build Coastguard Worker
1022*bb4ee6a4SAndroid Build Coastguard Worker // Parsing binary values
1023*bb4ee6a4SAndroid Build Coastguard Worker let res: SingleStruct<usize> = from_key_values::<SingleStruct<usize>>("m=0b1100").unwrap();
1024*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, 0b1100);
1025*bb4ee6a4SAndroid Build Coastguard Worker let res: SingleStruct<isize> = from_key_values::<SingleStruct<isize>>("m=-0b1100").unwrap();
1026*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, -0b1100);
1027*bb4ee6a4SAndroid Build Coastguard Worker
1028*bb4ee6a4SAndroid Build Coastguard Worker // Binary value outside range
1029*bb4ee6a4SAndroid Build Coastguard Worker let res: ParseError = from_key_values::<SingleStruct<usize>>("m=0b2").unwrap_err();
1030*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1031*bb4ee6a4SAndroid Build Coastguard Worker res,
1032*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1033*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidNumber,
1034*bb4ee6a4SAndroid Build Coastguard Worker pos: 2,
1035*bb4ee6a4SAndroid Build Coastguard Worker }
1036*bb4ee6a4SAndroid Build Coastguard Worker );
1037*bb4ee6a4SAndroid Build Coastguard Worker }
1038*bb4ee6a4SAndroid Build Coastguard Worker
1039*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_string()1040*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_string() {
1041*bb4ee6a4SAndroid Build Coastguard Worker let kv = "m=John";
1042*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1043*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "John".to_string());
1044*bb4ee6a4SAndroid Build Coastguard Worker
1045*bb4ee6a4SAndroid Build Coastguard Worker // Spaces are valid (but not recommended) in unquoted strings.
1046*bb4ee6a4SAndroid Build Coastguard Worker let kv = "m=John Doe";
1047*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1048*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "John Doe".to_string());
1049*bb4ee6a4SAndroid Build Coastguard Worker
1050*bb4ee6a4SAndroid Build Coastguard Worker // Empty string is not valid if unquoted
1051*bb4ee6a4SAndroid Build Coastguard Worker let kv = "m=";
1052*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<SingleStruct<String>>(kv).unwrap_err();
1053*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1054*bb4ee6a4SAndroid Build Coastguard Worker err,
1055*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1056*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedString,
1057*bb4ee6a4SAndroid Build Coastguard Worker pos: 2
1058*bb4ee6a4SAndroid Build Coastguard Worker }
1059*bb4ee6a4SAndroid Build Coastguard Worker );
1060*bb4ee6a4SAndroid Build Coastguard Worker
1061*bb4ee6a4SAndroid Build Coastguard Worker // Quoted strings.
1062*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m="John Doe""#;
1063*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1064*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "John Doe".to_string());
1065*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m='John Doe'"#;
1066*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1067*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "John Doe".to_string());
1068*bb4ee6a4SAndroid Build Coastguard Worker
1069*bb4ee6a4SAndroid Build Coastguard Worker // Empty quoted strings.
1070*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m="""#;
1071*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1072*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "".to_string());
1073*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m=''"#;
1074*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1075*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "".to_string());
1076*bb4ee6a4SAndroid Build Coastguard Worker
1077*bb4ee6a4SAndroid Build Coastguard Worker // "=", ",", "[", "]" and "'" in quote.
1078*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m="val = [10, 20, 'a']""#;
1079*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1080*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, r#"val = [10, 20, 'a']"#.to_string());
1081*bb4ee6a4SAndroid Build Coastguard Worker
1082*bb4ee6a4SAndroid Build Coastguard Worker // Quotes in unquoted strings are forbidden.
1083*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m=val="a""#;
1084*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<SingleStruct<String>>(kv).unwrap_err();
1085*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1086*bb4ee6a4SAndroid Build Coastguard Worker err,
1087*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1088*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidCharInString,
1089*bb4ee6a4SAndroid Build Coastguard Worker pos: 6
1090*bb4ee6a4SAndroid Build Coastguard Worker }
1091*bb4ee6a4SAndroid Build Coastguard Worker );
1092*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m=val='a'"#;
1093*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<SingleStruct<String>>(kv).unwrap_err();
1094*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1095*bb4ee6a4SAndroid Build Coastguard Worker err,
1096*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1097*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidCharInString,
1098*bb4ee6a4SAndroid Build Coastguard Worker pos: 6
1099*bb4ee6a4SAndroid Build Coastguard Worker }
1100*bb4ee6a4SAndroid Build Coastguard Worker );
1101*bb4ee6a4SAndroid Build Coastguard Worker
1102*bb4ee6a4SAndroid Build Coastguard Worker // Brackets in unquoted strings are forbidden.
1103*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m=val=[a]"#;
1104*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<SingleStruct<String>>(kv).unwrap_err();
1105*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1106*bb4ee6a4SAndroid Build Coastguard Worker err,
1107*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1108*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::InvalidCharInString,
1109*bb4ee6a4SAndroid Build Coastguard Worker pos: 6
1110*bb4ee6a4SAndroid Build Coastguard Worker }
1111*bb4ee6a4SAndroid Build Coastguard Worker );
1112*bb4ee6a4SAndroid Build Coastguard Worker
1113*bb4ee6a4SAndroid Build Coastguard Worker // Numbers and booleans are technically valid strings.
1114*bb4ee6a4SAndroid Build Coastguard Worker let kv = "m=10";
1115*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1116*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "10".to_string());
1117*bb4ee6a4SAndroid Build Coastguard Worker let kv = "m=false";
1118*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1119*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, "false".to_string());
1120*bb4ee6a4SAndroid Build Coastguard Worker
1121*bb4ee6a4SAndroid Build Coastguard Worker // Escaped quote.
1122*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m="Escaped \" quote""#;
1123*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1124*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, r#"Escaped " quote"#.to_string());
1125*bb4ee6a4SAndroid Build Coastguard Worker
1126*bb4ee6a4SAndroid Build Coastguard Worker // Escaped slash at end of string.
1127*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m="Escaped slash\\""#;
1128*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1129*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, r"Escaped slash\".to_string());
1130*bb4ee6a4SAndroid Build Coastguard Worker
1131*bb4ee6a4SAndroid Build Coastguard Worker // Characters within single quotes should not be escaped.
1132*bb4ee6a4SAndroid Build Coastguard Worker let kv = r#"m='Escaped \" quote'"#;
1133*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1134*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, r#"Escaped \" quote"#.to_string());
1135*bb4ee6a4SAndroid Build Coastguard Worker let kv = r"m='Escaped slash\\'";
1136*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<String>>(kv).unwrap();
1137*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.m, r"Escaped slash\\".to_string());
1138*bb4ee6a4SAndroid Build Coastguard Worker }
1139*bb4ee6a4SAndroid Build Coastguard Worker
1140*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_unit()1141*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_unit() {
1142*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<SingleStruct<()>>("m").unwrap();
1143*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<SingleStruct<()>>("m=").unwrap();
1144*bb4ee6a4SAndroid Build Coastguard Worker
1145*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<SingleStruct<()>>("").unwrap_err();
1146*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<SingleStruct<()>>("p").unwrap_err();
1147*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<SingleStruct<()>>("m=10").unwrap_err();
1148*bb4ee6a4SAndroid Build Coastguard Worker }
1149*bb4ee6a4SAndroid Build Coastguard Worker
1150*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_bool()1151*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_bool() {
1152*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<bool>>("m=true").unwrap();
1153*bb4ee6a4SAndroid Build Coastguard Worker assert!(res.m);
1154*bb4ee6a4SAndroid Build Coastguard Worker
1155*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<bool>>("m=false").unwrap();
1156*bb4ee6a4SAndroid Build Coastguard Worker assert!(!res.m);
1157*bb4ee6a4SAndroid Build Coastguard Worker
1158*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<bool>>("m").unwrap();
1159*bb4ee6a4SAndroid Build Coastguard Worker assert!(res.m);
1160*bb4ee6a4SAndroid Build Coastguard Worker
1161*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<bool>>("m=10").unwrap_err();
1162*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1163*bb4ee6a4SAndroid Build Coastguard Worker res,
1164*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1165*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedBoolean,
1166*bb4ee6a4SAndroid Build Coastguard Worker pos: 2,
1167*bb4ee6a4SAndroid Build Coastguard Worker }
1168*bb4ee6a4SAndroid Build Coastguard Worker );
1169*bb4ee6a4SAndroid Build Coastguard Worker
1170*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<SingleStruct<bool>>("m=").unwrap_err();
1171*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1172*bb4ee6a4SAndroid Build Coastguard Worker res,
1173*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1174*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedBoolean,
1175*bb4ee6a4SAndroid Build Coastguard Worker pos: 2,
1176*bb4ee6a4SAndroid Build Coastguard Worker }
1177*bb4ee6a4SAndroid Build Coastguard Worker );
1178*bb4ee6a4SAndroid Build Coastguard Worker }
1179*bb4ee6a4SAndroid Build Coastguard Worker
1180*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_complex_struct()1181*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_complex_struct() {
1182*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1183*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1184*bb4ee6a4SAndroid Build Coastguard Worker num: usize,
1185*bb4ee6a4SAndroid Build Coastguard Worker path: PathBuf,
1186*bb4ee6a4SAndroid Build Coastguard Worker enable: bool,
1187*bb4ee6a4SAndroid Build Coastguard Worker }
1188*bb4ee6a4SAndroid Build Coastguard Worker let kv = "num=54,path=/dev/foomatic,enable=false";
1189*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<TestStruct>(kv).unwrap();
1190*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1191*bb4ee6a4SAndroid Build Coastguard Worker res,
1192*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1193*bb4ee6a4SAndroid Build Coastguard Worker num: 54,
1194*bb4ee6a4SAndroid Build Coastguard Worker path: "/dev/foomatic".into(),
1195*bb4ee6a4SAndroid Build Coastguard Worker enable: false,
1196*bb4ee6a4SAndroid Build Coastguard Worker }
1197*bb4ee6a4SAndroid Build Coastguard Worker );
1198*bb4ee6a4SAndroid Build Coastguard Worker
1199*bb4ee6a4SAndroid Build Coastguard Worker let kv = "num=0x54,path=/dev/foomatic,enable=false";
1200*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<TestStruct>(kv).unwrap();
1201*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1202*bb4ee6a4SAndroid Build Coastguard Worker res,
1203*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1204*bb4ee6a4SAndroid Build Coastguard Worker num: 0x54,
1205*bb4ee6a4SAndroid Build Coastguard Worker path: "/dev/foomatic".into(),
1206*bb4ee6a4SAndroid Build Coastguard Worker enable: false,
1207*bb4ee6a4SAndroid Build Coastguard Worker }
1208*bb4ee6a4SAndroid Build Coastguard Worker );
1209*bb4ee6a4SAndroid Build Coastguard Worker
1210*bb4ee6a4SAndroid Build Coastguard Worker let kv = "enable,path=/usr/lib/libossom.so.1,num=12";
1211*bb4ee6a4SAndroid Build Coastguard Worker let res = from_key_values::<TestStruct>(kv).unwrap();
1212*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1213*bb4ee6a4SAndroid Build Coastguard Worker res,
1214*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1215*bb4ee6a4SAndroid Build Coastguard Worker num: 12,
1216*bb4ee6a4SAndroid Build Coastguard Worker path: "/usr/lib/libossom.so.1".into(),
1217*bb4ee6a4SAndroid Build Coastguard Worker enable: true,
1218*bb4ee6a4SAndroid Build Coastguard Worker }
1219*bb4ee6a4SAndroid Build Coastguard Worker );
1220*bb4ee6a4SAndroid Build Coastguard Worker
1221*bb4ee6a4SAndroid Build Coastguard Worker // Braces specified at top-level.
1222*bb4ee6a4SAndroid Build Coastguard Worker let kv = "[enable,path=/usr/lib/libossom.so.1,num=12]";
1223*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_key_values::<TestStruct>(kv).is_err());
1224*bb4ee6a4SAndroid Build Coastguard Worker }
1225*bb4ee6a4SAndroid Build Coastguard Worker
1226*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_unknown_field()1227*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_unknown_field() {
1228*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1229*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields)]
1230*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1231*bb4ee6a4SAndroid Build Coastguard Worker num: usize,
1232*bb4ee6a4SAndroid Build Coastguard Worker path: PathBuf,
1233*bb4ee6a4SAndroid Build Coastguard Worker enable: bool,
1234*bb4ee6a4SAndroid Build Coastguard Worker }
1235*bb4ee6a4SAndroid Build Coastguard Worker
1236*bb4ee6a4SAndroid Build Coastguard Worker let kv = "enable,path=/usr/lib/libossom.so.1,num=12,foo=bar";
1237*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_key_values::<TestStruct>(kv).is_err());
1238*bb4ee6a4SAndroid Build Coastguard Worker }
1239*bb4ee6a4SAndroid Build Coastguard Worker
1240*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_option()1241*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_option() {
1242*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1243*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1244*bb4ee6a4SAndroid Build Coastguard Worker num: u32,
1245*bb4ee6a4SAndroid Build Coastguard Worker opt: Option<u32>,
1246*bb4ee6a4SAndroid Build Coastguard Worker }
1247*bb4ee6a4SAndroid Build Coastguard Worker let kv = "num=16,opt=12";
1248*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1249*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1250*bb4ee6a4SAndroid Build Coastguard Worker res,
1251*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1252*bb4ee6a4SAndroid Build Coastguard Worker num: 16,
1253*bb4ee6a4SAndroid Build Coastguard Worker opt: Some(12),
1254*bb4ee6a4SAndroid Build Coastguard Worker }
1255*bb4ee6a4SAndroid Build Coastguard Worker );
1256*bb4ee6a4SAndroid Build Coastguard Worker
1257*bb4ee6a4SAndroid Build Coastguard Worker let kv = "num=16";
1258*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1259*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, TestStruct { num: 16, opt: None });
1260*bb4ee6a4SAndroid Build Coastguard Worker
1261*bb4ee6a4SAndroid Build Coastguard Worker let kv = "";
1262*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_key_values::<TestStruct>(kv).is_err());
1263*bb4ee6a4SAndroid Build Coastguard Worker }
1264*bb4ee6a4SAndroid Build Coastguard Worker
1265*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_optional_struct_with_default()1266*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_optional_struct_with_default() {
1267*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1268*bb4ee6a4SAndroid Build Coastguard Worker struct DefaultStruct {
1269*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1270*bb4ee6a4SAndroid Build Coastguard Worker param: u32,
1271*bb4ee6a4SAndroid Build Coastguard Worker }
1272*bb4ee6a4SAndroid Build Coastguard Worker
1273*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1274*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1275*bb4ee6a4SAndroid Build Coastguard Worker flag: Option<DefaultStruct>,
1276*bb4ee6a4SAndroid Build Coastguard Worker }
1277*bb4ee6a4SAndroid Build Coastguard Worker
1278*bb4ee6a4SAndroid Build Coastguard Worker // Specify member explicitly
1279*bb4ee6a4SAndroid Build Coastguard Worker let kv = "flag=[param=12]";
1280*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1281*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1282*bb4ee6a4SAndroid Build Coastguard Worker res,
1283*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1284*bb4ee6a4SAndroid Build Coastguard Worker flag: Some(DefaultStruct { param: 12 })
1285*bb4ee6a4SAndroid Build Coastguard Worker }
1286*bb4ee6a4SAndroid Build Coastguard Worker );
1287*bb4ee6a4SAndroid Build Coastguard Worker
1288*bb4ee6a4SAndroid Build Coastguard Worker // No member specified, braces present.
1289*bb4ee6a4SAndroid Build Coastguard Worker let kv = "flag=[]";
1290*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1291*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1292*bb4ee6a4SAndroid Build Coastguard Worker res,
1293*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1294*bb4ee6a4SAndroid Build Coastguard Worker flag: Some(DefaultStruct { param: 0 })
1295*bb4ee6a4SAndroid Build Coastguard Worker }
1296*bb4ee6a4SAndroid Build Coastguard Worker );
1297*bb4ee6a4SAndroid Build Coastguard Worker
1298*bb4ee6a4SAndroid Build Coastguard Worker // No member specified, no braces.
1299*bb4ee6a4SAndroid Build Coastguard Worker let kv = "flag=";
1300*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1301*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1302*bb4ee6a4SAndroid Build Coastguard Worker res,
1303*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1304*bb4ee6a4SAndroid Build Coastguard Worker flag: Some(DefaultStruct { param: 0 })
1305*bb4ee6a4SAndroid Build Coastguard Worker }
1306*bb4ee6a4SAndroid Build Coastguard Worker );
1307*bb4ee6a4SAndroid Build Coastguard Worker
1308*bb4ee6a4SAndroid Build Coastguard Worker // No member specified, no braces, no equal sign.
1309*bb4ee6a4SAndroid Build Coastguard Worker let kv = "flag";
1310*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1311*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1312*bb4ee6a4SAndroid Build Coastguard Worker res,
1313*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1314*bb4ee6a4SAndroid Build Coastguard Worker flag: Some(DefaultStruct { param: 0 })
1315*bb4ee6a4SAndroid Build Coastguard Worker }
1316*bb4ee6a4SAndroid Build Coastguard Worker );
1317*bb4ee6a4SAndroid Build Coastguard Worker
1318*bb4ee6a4SAndroid Build Coastguard Worker // No closing brace.
1319*bb4ee6a4SAndroid Build Coastguard Worker let kv = "flag=[";
1320*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_key_values::<TestStruct>(kv).is_err());
1321*bb4ee6a4SAndroid Build Coastguard Worker
1322*bb4ee6a4SAndroid Build Coastguard Worker // No opening brace.
1323*bb4ee6a4SAndroid Build Coastguard Worker let kv = "flag=]";
1324*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_key_values::<TestStruct>(kv).is_err());
1325*bb4ee6a4SAndroid Build Coastguard Worker }
1326*bb4ee6a4SAndroid Build Coastguard Worker
1327*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_optional_struct_within_flattened()1328*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_optional_struct_within_flattened() {
1329*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1330*bb4ee6a4SAndroid Build Coastguard Worker struct FlatStruct {
1331*bb4ee6a4SAndroid Build Coastguard Worker a: u32,
1332*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1333*bb4ee6a4SAndroid Build Coastguard Worker b: String,
1334*bb4ee6a4SAndroid Build Coastguard Worker }
1335*bb4ee6a4SAndroid Build Coastguard Worker
1336*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1337*bb4ee6a4SAndroid Build Coastguard Worker struct DefaultStruct {
1338*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1339*bb4ee6a4SAndroid Build Coastguard Worker param: u32,
1340*bb4ee6a4SAndroid Build Coastguard Worker }
1341*bb4ee6a4SAndroid Build Coastguard Worker
1342*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1343*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1344*bb4ee6a4SAndroid Build Coastguard Worker #[serde(flatten)]
1345*bb4ee6a4SAndroid Build Coastguard Worker flat: FlatStruct,
1346*bb4ee6a4SAndroid Build Coastguard Worker flag: Option<DefaultStruct>,
1347*bb4ee6a4SAndroid Build Coastguard Worker }
1348*bb4ee6a4SAndroid Build Coastguard Worker
1349*bb4ee6a4SAndroid Build Coastguard Worker // Everything specified.
1350*bb4ee6a4SAndroid Build Coastguard Worker let kv = "a=10,b=foomatic,flag=[param=24]";
1351*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1352*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1353*bb4ee6a4SAndroid Build Coastguard Worker res,
1354*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1355*bb4ee6a4SAndroid Build Coastguard Worker flat: FlatStruct {
1356*bb4ee6a4SAndroid Build Coastguard Worker a: 10,
1357*bb4ee6a4SAndroid Build Coastguard Worker b: "foomatic".into(),
1358*bb4ee6a4SAndroid Build Coastguard Worker },
1359*bb4ee6a4SAndroid Build Coastguard Worker flag: Some(DefaultStruct { param: 24 })
1360*bb4ee6a4SAndroid Build Coastguard Worker }
1361*bb4ee6a4SAndroid Build Coastguard Worker );
1362*bb4ee6a4SAndroid Build Coastguard Worker
1363*bb4ee6a4SAndroid Build Coastguard Worker // Flag left to default value.
1364*bb4ee6a4SAndroid Build Coastguard Worker let kv = "a=10,b=foomatic,flag";
1365*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1366*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1367*bb4ee6a4SAndroid Build Coastguard Worker res,
1368*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1369*bb4ee6a4SAndroid Build Coastguard Worker flat: FlatStruct {
1370*bb4ee6a4SAndroid Build Coastguard Worker a: 10,
1371*bb4ee6a4SAndroid Build Coastguard Worker b: "foomatic".into(),
1372*bb4ee6a4SAndroid Build Coastguard Worker },
1373*bb4ee6a4SAndroid Build Coastguard Worker flag: Some(DefaultStruct { param: 0 })
1374*bb4ee6a4SAndroid Build Coastguard Worker }
1375*bb4ee6a4SAndroid Build Coastguard Worker );
1376*bb4ee6a4SAndroid Build Coastguard Worker
1377*bb4ee6a4SAndroid Build Coastguard Worker // Flattened default value unspecified.
1378*bb4ee6a4SAndroid Build Coastguard Worker let kv = "a=10,flag=[param=24]";
1379*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1380*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1381*bb4ee6a4SAndroid Build Coastguard Worker res,
1382*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1383*bb4ee6a4SAndroid Build Coastguard Worker flat: FlatStruct {
1384*bb4ee6a4SAndroid Build Coastguard Worker a: 10,
1385*bb4ee6a4SAndroid Build Coastguard Worker b: Default::default(),
1386*bb4ee6a4SAndroid Build Coastguard Worker },
1387*bb4ee6a4SAndroid Build Coastguard Worker flag: Some(DefaultStruct { param: 24 })
1388*bb4ee6a4SAndroid Build Coastguard Worker }
1389*bb4ee6a4SAndroid Build Coastguard Worker );
1390*bb4ee6a4SAndroid Build Coastguard Worker
1391*bb4ee6a4SAndroid Build Coastguard Worker // No optional, no default value.
1392*bb4ee6a4SAndroid Build Coastguard Worker let kv = "a=10";
1393*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values(kv).unwrap();
1394*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1395*bb4ee6a4SAndroid Build Coastguard Worker res,
1396*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1397*bb4ee6a4SAndroid Build Coastguard Worker flat: FlatStruct {
1398*bb4ee6a4SAndroid Build Coastguard Worker a: 10,
1399*bb4ee6a4SAndroid Build Coastguard Worker b: Default::default(),
1400*bb4ee6a4SAndroid Build Coastguard Worker },
1401*bb4ee6a4SAndroid Build Coastguard Worker flag: None,
1402*bb4ee6a4SAndroid Build Coastguard Worker }
1403*bb4ee6a4SAndroid Build Coastguard Worker );
1404*bb4ee6a4SAndroid Build Coastguard Worker
1405*bb4ee6a4SAndroid Build Coastguard Worker // Required member unspecified.
1406*bb4ee6a4SAndroid Build Coastguard Worker let kv = "b=foomatic,flag=[param=24]";
1407*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_key_values::<TestStruct>(kv).is_err());
1408*bb4ee6a4SAndroid Build Coastguard Worker
1409*bb4ee6a4SAndroid Build Coastguard Worker // Braces specified at top-level.
1410*bb4ee6a4SAndroid Build Coastguard Worker let kv = "[a=10,b=foomatic,flag=[param=24]]";
1411*bb4ee6a4SAndroid Build Coastguard Worker assert!(from_key_values::<TestStruct>(kv).is_err());
1412*bb4ee6a4SAndroid Build Coastguard Worker }
1413*bb4ee6a4SAndroid Build Coastguard Worker
1414*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_enum()1415*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_enum() {
1416*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1417*bb4ee6a4SAndroid Build Coastguard Worker enum TestEnum {
1418*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename = "first")]
1419*bb4ee6a4SAndroid Build Coastguard Worker FirstVariant,
1420*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename = "second")]
1421*bb4ee6a4SAndroid Build Coastguard Worker SecondVariant,
1422*bb4ee6a4SAndroid Build Coastguard Worker }
1423*bb4ee6a4SAndroid Build Coastguard Worker let res: TestEnum = from_key_values("first").unwrap();
1424*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, TestEnum::FirstVariant,);
1425*bb4ee6a4SAndroid Build Coastguard Worker
1426*bb4ee6a4SAndroid Build Coastguard Worker let res: TestEnum = from_key_values("second").unwrap();
1427*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, TestEnum::SecondVariant,);
1428*bb4ee6a4SAndroid Build Coastguard Worker
1429*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<TestEnum>("third").unwrap_err();
1430*bb4ee6a4SAndroid Build Coastguard Worker }
1431*bb4ee6a4SAndroid Build Coastguard Worker
1432*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_embedded_enum()1433*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_embedded_enum() {
1434*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1435*bb4ee6a4SAndroid Build Coastguard Worker enum TestEnum {
1436*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename = "first")]
1437*bb4ee6a4SAndroid Build Coastguard Worker FirstVariant,
1438*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename = "second")]
1439*bb4ee6a4SAndroid Build Coastguard Worker SecondVariant,
1440*bb4ee6a4SAndroid Build Coastguard Worker }
1441*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1442*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1443*bb4ee6a4SAndroid Build Coastguard Worker variant: TestEnum,
1444*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1445*bb4ee6a4SAndroid Build Coastguard Worker active: bool,
1446*bb4ee6a4SAndroid Build Coastguard Worker }
1447*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("variant=first").unwrap();
1448*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1449*bb4ee6a4SAndroid Build Coastguard Worker res,
1450*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1451*bb4ee6a4SAndroid Build Coastguard Worker variant: TestEnum::FirstVariant,
1452*bb4ee6a4SAndroid Build Coastguard Worker active: false,
1453*bb4ee6a4SAndroid Build Coastguard Worker }
1454*bb4ee6a4SAndroid Build Coastguard Worker );
1455*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("variant=second,active=true").unwrap();
1456*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1457*bb4ee6a4SAndroid Build Coastguard Worker res,
1458*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1459*bb4ee6a4SAndroid Build Coastguard Worker variant: TestEnum::SecondVariant,
1460*bb4ee6a4SAndroid Build Coastguard Worker active: true,
1461*bb4ee6a4SAndroid Build Coastguard Worker }
1462*bb4ee6a4SAndroid Build Coastguard Worker );
1463*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("active=true,variant=second").unwrap();
1464*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1465*bb4ee6a4SAndroid Build Coastguard Worker res,
1466*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1467*bb4ee6a4SAndroid Build Coastguard Worker variant: TestEnum::SecondVariant,
1468*bb4ee6a4SAndroid Build Coastguard Worker active: true,
1469*bb4ee6a4SAndroid Build Coastguard Worker }
1470*bb4ee6a4SAndroid Build Coastguard Worker );
1471*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("active,variant=second").unwrap();
1472*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1473*bb4ee6a4SAndroid Build Coastguard Worker res,
1474*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1475*bb4ee6a4SAndroid Build Coastguard Worker variant: TestEnum::SecondVariant,
1476*bb4ee6a4SAndroid Build Coastguard Worker active: true,
1477*bb4ee6a4SAndroid Build Coastguard Worker }
1478*bb4ee6a4SAndroid Build Coastguard Worker );
1479*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("active=false,variant=second").unwrap();
1480*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1481*bb4ee6a4SAndroid Build Coastguard Worker res,
1482*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1483*bb4ee6a4SAndroid Build Coastguard Worker variant: TestEnum::SecondVariant,
1484*bb4ee6a4SAndroid Build Coastguard Worker active: false,
1485*bb4ee6a4SAndroid Build Coastguard Worker }
1486*bb4ee6a4SAndroid Build Coastguard Worker );
1487*bb4ee6a4SAndroid Build Coastguard Worker }
1488*bb4ee6a4SAndroid Build Coastguard Worker
1489*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_untagged_enum()1490*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_untagged_enum() {
1491*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1492*bb4ee6a4SAndroid Build Coastguard Worker #[serde(untagged)]
1493*bb4ee6a4SAndroid Build Coastguard Worker enum TestEnum {
1494*bb4ee6a4SAndroid Build Coastguard Worker FirstVariant { first: u32 },
1495*bb4ee6a4SAndroid Build Coastguard Worker SecondVariant { second: bool },
1496*bb4ee6a4SAndroid Build Coastguard Worker }
1497*bb4ee6a4SAndroid Build Coastguard Worker
1498*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1499*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1500*bb4ee6a4SAndroid Build Coastguard Worker #[serde(flatten)]
1501*bb4ee6a4SAndroid Build Coastguard Worker variant: TestEnum,
1502*bb4ee6a4SAndroid Build Coastguard Worker }
1503*bb4ee6a4SAndroid Build Coastguard Worker
1504*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("first=10").unwrap();
1505*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.variant, TestEnum::FirstVariant { first: 10 });
1506*bb4ee6a4SAndroid Build Coastguard Worker
1507*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("second=false").unwrap();
1508*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.variant, TestEnum::SecondVariant { second: false },);
1509*bb4ee6a4SAndroid Build Coastguard Worker
1510*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("second").unwrap();
1511*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res.variant, TestEnum::SecondVariant { second: true },);
1512*bb4ee6a4SAndroid Build Coastguard Worker
1513*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<TestStruct>("third=10").unwrap_err();
1514*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<TestStruct>("first=some_string").unwrap_err();
1515*bb4ee6a4SAndroid Build Coastguard Worker from_key_values::<TestStruct>("second=10").unwrap_err();
1516*bb4ee6a4SAndroid Build Coastguard Worker }
1517*bb4ee6a4SAndroid Build Coastguard Worker
1518*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_first_arg_string()1519*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_first_arg_string() {
1520*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1521*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1522*bb4ee6a4SAndroid Build Coastguard Worker name: String,
1523*bb4ee6a4SAndroid Build Coastguard Worker num: u8,
1524*bb4ee6a4SAndroid Build Coastguard Worker }
1525*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("name=foo,num=12").unwrap();
1526*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1527*bb4ee6a4SAndroid Build Coastguard Worker res,
1528*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1529*bb4ee6a4SAndroid Build Coastguard Worker name: "foo".into(),
1530*bb4ee6a4SAndroid Build Coastguard Worker num: 12,
1531*bb4ee6a4SAndroid Build Coastguard Worker }
1532*bb4ee6a4SAndroid Build Coastguard Worker );
1533*bb4ee6a4SAndroid Build Coastguard Worker
1534*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("foo,num=12").unwrap();
1535*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1536*bb4ee6a4SAndroid Build Coastguard Worker res,
1537*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1538*bb4ee6a4SAndroid Build Coastguard Worker name: "foo".into(),
1539*bb4ee6a4SAndroid Build Coastguard Worker num: 12,
1540*bb4ee6a4SAndroid Build Coastguard Worker }
1541*bb4ee6a4SAndroid Build Coastguard Worker );
1542*bb4ee6a4SAndroid Build Coastguard Worker }
1543*bb4ee6a4SAndroid Build Coastguard Worker
1544*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_first_arg_int()1545*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_first_arg_int() {
1546*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1547*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1548*bb4ee6a4SAndroid Build Coastguard Worker num: u8,
1549*bb4ee6a4SAndroid Build Coastguard Worker name: String,
1550*bb4ee6a4SAndroid Build Coastguard Worker }
1551*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("name=foo,num=12").unwrap();
1552*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1553*bb4ee6a4SAndroid Build Coastguard Worker res,
1554*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1555*bb4ee6a4SAndroid Build Coastguard Worker num: 12,
1556*bb4ee6a4SAndroid Build Coastguard Worker name: "foo".into(),
1557*bb4ee6a4SAndroid Build Coastguard Worker }
1558*bb4ee6a4SAndroid Build Coastguard Worker );
1559*bb4ee6a4SAndroid Build Coastguard Worker
1560*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("12,name=foo").unwrap();
1561*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1562*bb4ee6a4SAndroid Build Coastguard Worker res,
1563*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1564*bb4ee6a4SAndroid Build Coastguard Worker num: 12,
1565*bb4ee6a4SAndroid Build Coastguard Worker name: "foo".into(),
1566*bb4ee6a4SAndroid Build Coastguard Worker }
1567*bb4ee6a4SAndroid Build Coastguard Worker );
1568*bb4ee6a4SAndroid Build Coastguard Worker }
1569*bb4ee6a4SAndroid Build Coastguard Worker
1570*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_tuple()1571*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_tuple() {
1572*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1573*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1574*bb4ee6a4SAndroid Build Coastguard Worker size: (u32, u32),
1575*bb4ee6a4SAndroid Build Coastguard Worker }
1576*bb4ee6a4SAndroid Build Coastguard Worker
1577*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("size=[320,200]").unwrap();
1578*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(res, TestStruct { size: (320, 200) });
1579*bb4ee6a4SAndroid Build Coastguard Worker
1580*bb4ee6a4SAndroid Build Coastguard Worker // Unterminated tuple.
1581*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<TestStruct>("size=[320]").unwrap_err();
1582*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1583*bb4ee6a4SAndroid Build Coastguard Worker err,
1584*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1585*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::SerdeError("invalid length 1, expected a tuple of size 2".into()),
1586*bb4ee6a4SAndroid Build Coastguard Worker pos: 0,
1587*bb4ee6a4SAndroid Build Coastguard Worker }
1588*bb4ee6a4SAndroid Build Coastguard Worker );
1589*bb4ee6a4SAndroid Build Coastguard Worker
1590*bb4ee6a4SAndroid Build Coastguard Worker // Too many elements in tuple.
1591*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<TestStruct>("size=[320,200,255]").unwrap_err();
1592*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1593*bb4ee6a4SAndroid Build Coastguard Worker err,
1594*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1595*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedCloseBracket,
1596*bb4ee6a4SAndroid Build Coastguard Worker pos: 14,
1597*bb4ee6a4SAndroid Build Coastguard Worker }
1598*bb4ee6a4SAndroid Build Coastguard Worker );
1599*bb4ee6a4SAndroid Build Coastguard Worker
1600*bb4ee6a4SAndroid Build Coastguard Worker // Non-closed sequence is invalid.
1601*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<TestStruct>("size=[320,200").unwrap_err();
1602*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1603*bb4ee6a4SAndroid Build Coastguard Worker err,
1604*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1605*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedCloseBracket,
1606*bb4ee6a4SAndroid Build Coastguard Worker pos: 13,
1607*bb4ee6a4SAndroid Build Coastguard Worker }
1608*bb4ee6a4SAndroid Build Coastguard Worker );
1609*bb4ee6a4SAndroid Build Coastguard Worker }
1610*bb4ee6a4SAndroid Build Coastguard Worker
1611*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_vector()1612*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_vector() {
1613*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1614*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1615*bb4ee6a4SAndroid Build Coastguard Worker numbers: Vec<u32>,
1616*bb4ee6a4SAndroid Build Coastguard Worker }
1617*bb4ee6a4SAndroid Build Coastguard Worker
1618*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("numbers=[1,2,4,8,16,32,64]").unwrap();
1619*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1620*bb4ee6a4SAndroid Build Coastguard Worker res,
1621*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1622*bb4ee6a4SAndroid Build Coastguard Worker numbers: vec![1, 2, 4, 8, 16, 32, 64],
1623*bb4ee6a4SAndroid Build Coastguard Worker }
1624*bb4ee6a4SAndroid Build Coastguard Worker );
1625*bb4ee6a4SAndroid Build Coastguard Worker }
1626*bb4ee6a4SAndroid Build Coastguard Worker
1627*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_vector_of_strings()1628*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_vector_of_strings() {
1629*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1630*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1631*bb4ee6a4SAndroid Build Coastguard Worker strs: Vec<String>,
1632*bb4ee6a4SAndroid Build Coastguard Worker }
1633*bb4ee6a4SAndroid Build Coastguard Worker
1634*bb4ee6a4SAndroid Build Coastguard Worker // Unquoted strings
1635*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct =
1636*bb4ee6a4SAndroid Build Coastguard Worker from_key_values(r#"strs=[singleword,camel_cased,kebab-cased]"#).unwrap();
1637*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1638*bb4ee6a4SAndroid Build Coastguard Worker res,
1639*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1640*bb4ee6a4SAndroid Build Coastguard Worker strs: vec![
1641*bb4ee6a4SAndroid Build Coastguard Worker "singleword".into(),
1642*bb4ee6a4SAndroid Build Coastguard Worker "camel_cased".into(),
1643*bb4ee6a4SAndroid Build Coastguard Worker "kebab-cased".into()
1644*bb4ee6a4SAndroid Build Coastguard Worker ],
1645*bb4ee6a4SAndroid Build Coastguard Worker }
1646*bb4ee6a4SAndroid Build Coastguard Worker );
1647*bb4ee6a4SAndroid Build Coastguard Worker
1648*bb4ee6a4SAndroid Build Coastguard Worker // All quoted strings
1649*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct =
1650*bb4ee6a4SAndroid Build Coastguard Worker from_key_values(r#"strs=["first string","second string","third string"]"#).unwrap();
1651*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1652*bb4ee6a4SAndroid Build Coastguard Worker res,
1653*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1654*bb4ee6a4SAndroid Build Coastguard Worker strs: vec![
1655*bb4ee6a4SAndroid Build Coastguard Worker "first string".into(),
1656*bb4ee6a4SAndroid Build Coastguard Worker "second string".into(),
1657*bb4ee6a4SAndroid Build Coastguard Worker "third string".into()
1658*bb4ee6a4SAndroid Build Coastguard Worker ],
1659*bb4ee6a4SAndroid Build Coastguard Worker }
1660*bb4ee6a4SAndroid Build Coastguard Worker );
1661*bb4ee6a4SAndroid Build Coastguard Worker
1662*bb4ee6a4SAndroid Build Coastguard Worker // Mix
1663*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct =
1664*bb4ee6a4SAndroid Build Coastguard Worker from_key_values(r#"strs=[unquoted,"quoted string",'quoted with escape "']"#).unwrap();
1665*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1666*bb4ee6a4SAndroid Build Coastguard Worker res,
1667*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1668*bb4ee6a4SAndroid Build Coastguard Worker strs: vec![
1669*bb4ee6a4SAndroid Build Coastguard Worker "unquoted".into(),
1670*bb4ee6a4SAndroid Build Coastguard Worker "quoted string".into(),
1671*bb4ee6a4SAndroid Build Coastguard Worker "quoted with escape \"".into()
1672*bb4ee6a4SAndroid Build Coastguard Worker ],
1673*bb4ee6a4SAndroid Build Coastguard Worker }
1674*bb4ee6a4SAndroid Build Coastguard Worker );
1675*bb4ee6a4SAndroid Build Coastguard Worker }
1676*bb4ee6a4SAndroid Build Coastguard Worker
1677*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_vector_of_structs()1678*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_vector_of_structs() {
1679*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1680*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields)]
1681*bb4ee6a4SAndroid Build Coastguard Worker struct Display {
1682*bb4ee6a4SAndroid Build Coastguard Worker size: (u32, u32),
1683*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1684*bb4ee6a4SAndroid Build Coastguard Worker disabled: bool,
1685*bb4ee6a4SAndroid Build Coastguard Worker }
1686*bb4ee6a4SAndroid Build Coastguard Worker
1687*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1688*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields)]
1689*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1690*bb4ee6a4SAndroid Build Coastguard Worker displays: Vec<Display>,
1691*bb4ee6a4SAndroid Build Coastguard Worker hostname: Option<String>,
1692*bb4ee6a4SAndroid Build Coastguard Worker }
1693*bb4ee6a4SAndroid Build Coastguard Worker
1694*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("displays=[[size=[640,480]]]").unwrap();
1695*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1696*bb4ee6a4SAndroid Build Coastguard Worker res,
1697*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1698*bb4ee6a4SAndroid Build Coastguard Worker displays: vec![Display {
1699*bb4ee6a4SAndroid Build Coastguard Worker size: (640, 480),
1700*bb4ee6a4SAndroid Build Coastguard Worker disabled: false,
1701*bb4ee6a4SAndroid Build Coastguard Worker }],
1702*bb4ee6a4SAndroid Build Coastguard Worker hostname: None,
1703*bb4ee6a4SAndroid Build Coastguard Worker }
1704*bb4ee6a4SAndroid Build Coastguard Worker );
1705*bb4ee6a4SAndroid Build Coastguard Worker
1706*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct =
1707*bb4ee6a4SAndroid Build Coastguard Worker from_key_values("hostname=crosmatic,displays=[[size=[800,600],disabled]]").unwrap();
1708*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1709*bb4ee6a4SAndroid Build Coastguard Worker res,
1710*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1711*bb4ee6a4SAndroid Build Coastguard Worker displays: vec![Display {
1712*bb4ee6a4SAndroid Build Coastguard Worker size: (800, 600),
1713*bb4ee6a4SAndroid Build Coastguard Worker disabled: true,
1714*bb4ee6a4SAndroid Build Coastguard Worker }],
1715*bb4ee6a4SAndroid Build Coastguard Worker hostname: Some("crosmatic".to_string()),
1716*bb4ee6a4SAndroid Build Coastguard Worker }
1717*bb4ee6a4SAndroid Build Coastguard Worker );
1718*bb4ee6a4SAndroid Build Coastguard Worker
1719*bb4ee6a4SAndroid Build Coastguard Worker // First field of a struct does not need to be named even if it is not the top-level struct.
1720*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct =
1721*bb4ee6a4SAndroid Build Coastguard Worker from_key_values("displays=[[[640,480]],[[800,600],disabled]]").unwrap();
1722*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1723*bb4ee6a4SAndroid Build Coastguard Worker res,
1724*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1725*bb4ee6a4SAndroid Build Coastguard Worker displays: vec![
1726*bb4ee6a4SAndroid Build Coastguard Worker Display {
1727*bb4ee6a4SAndroid Build Coastguard Worker size: (640, 480),
1728*bb4ee6a4SAndroid Build Coastguard Worker disabled: false,
1729*bb4ee6a4SAndroid Build Coastguard Worker },
1730*bb4ee6a4SAndroid Build Coastguard Worker Display {
1731*bb4ee6a4SAndroid Build Coastguard Worker size: (800, 600),
1732*bb4ee6a4SAndroid Build Coastguard Worker disabled: true,
1733*bb4ee6a4SAndroid Build Coastguard Worker }
1734*bb4ee6a4SAndroid Build Coastguard Worker ],
1735*bb4ee6a4SAndroid Build Coastguard Worker hostname: None,
1736*bb4ee6a4SAndroid Build Coastguard Worker }
1737*bb4ee6a4SAndroid Build Coastguard Worker );
1738*bb4ee6a4SAndroid Build Coastguard Worker
1739*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct =
1740*bb4ee6a4SAndroid Build Coastguard Worker from_key_values("displays=[[[1024,768]],[size=[800,600],disabled]],hostname=crosmatic")
1741*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
1742*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1743*bb4ee6a4SAndroid Build Coastguard Worker res,
1744*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1745*bb4ee6a4SAndroid Build Coastguard Worker displays: vec![
1746*bb4ee6a4SAndroid Build Coastguard Worker Display {
1747*bb4ee6a4SAndroid Build Coastguard Worker size: (1024, 768),
1748*bb4ee6a4SAndroid Build Coastguard Worker disabled: false,
1749*bb4ee6a4SAndroid Build Coastguard Worker },
1750*bb4ee6a4SAndroid Build Coastguard Worker Display {
1751*bb4ee6a4SAndroid Build Coastguard Worker size: (800, 600),
1752*bb4ee6a4SAndroid Build Coastguard Worker disabled: true,
1753*bb4ee6a4SAndroid Build Coastguard Worker }
1754*bb4ee6a4SAndroid Build Coastguard Worker ],
1755*bb4ee6a4SAndroid Build Coastguard Worker hostname: Some("crosmatic".to_string()),
1756*bb4ee6a4SAndroid Build Coastguard Worker }
1757*bb4ee6a4SAndroid Build Coastguard Worker );
1758*bb4ee6a4SAndroid Build Coastguard Worker }
1759*bb4ee6a4SAndroid Build Coastguard Worker
1760*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_set()1761*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_set() {
1762*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Eq, Debug, PartialOrd, Ord)]
1763*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
1764*bb4ee6a4SAndroid Build Coastguard Worker enum Flags {
1765*bb4ee6a4SAndroid Build Coastguard Worker Awesome,
1766*bb4ee6a4SAndroid Build Coastguard Worker Fluffy,
1767*bb4ee6a4SAndroid Build Coastguard Worker Transparent,
1768*bb4ee6a4SAndroid Build Coastguard Worker }
1769*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1770*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1771*bb4ee6a4SAndroid Build Coastguard Worker flags: BTreeSet<Flags>,
1772*bb4ee6a4SAndroid Build Coastguard Worker }
1773*bb4ee6a4SAndroid Build Coastguard Worker
1774*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("flags=[awesome,fluffy]").unwrap();
1775*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1776*bb4ee6a4SAndroid Build Coastguard Worker res,
1777*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1778*bb4ee6a4SAndroid Build Coastguard Worker flags: BTreeSet::from([Flags::Awesome, Flags::Fluffy]),
1779*bb4ee6a4SAndroid Build Coastguard Worker }
1780*bb4ee6a4SAndroid Build Coastguard Worker );
1781*bb4ee6a4SAndroid Build Coastguard Worker
1782*bb4ee6a4SAndroid Build Coastguard Worker // Unknown enum variant?
1783*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<TestStruct>("flags=[awesome,spiky]").unwrap_err();
1784*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1785*bb4ee6a4SAndroid Build Coastguard Worker err,
1786*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1787*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::SerdeError(
1788*bb4ee6a4SAndroid Build Coastguard Worker "unknown variant `spiky`, expected one of `awesome`, `fluffy`, `transparent`"
1789*bb4ee6a4SAndroid Build Coastguard Worker .into()
1790*bb4ee6a4SAndroid Build Coastguard Worker ),
1791*bb4ee6a4SAndroid Build Coastguard Worker pos: 0,
1792*bb4ee6a4SAndroid Build Coastguard Worker }
1793*bb4ee6a4SAndroid Build Coastguard Worker );
1794*bb4ee6a4SAndroid Build Coastguard Worker }
1795*bb4ee6a4SAndroid Build Coastguard Worker
1796*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_struct_and_tuple_enum()1797*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_struct_and_tuple_enum() {
1798*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1799*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
1800*bb4ee6a4SAndroid Build Coastguard Worker enum VideoMode {
1801*bb4ee6a4SAndroid Build Coastguard Worker Fullscreen,
1802*bb4ee6a4SAndroid Build Coastguard Worker WindowAsTuple(u32, u32),
1803*bb4ee6a4SAndroid Build Coastguard Worker WindowAsStruct { width: u32, height: u32 },
1804*bb4ee6a4SAndroid Build Coastguard Worker }
1805*bb4ee6a4SAndroid Build Coastguard Worker
1806*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1807*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1808*bb4ee6a4SAndroid Build Coastguard Worker mode: VideoMode,
1809*bb4ee6a4SAndroid Build Coastguard Worker }
1810*bb4ee6a4SAndroid Build Coastguard Worker
1811*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("mode=fullscreen").unwrap();
1812*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1813*bb4ee6a4SAndroid Build Coastguard Worker res,
1814*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1815*bb4ee6a4SAndroid Build Coastguard Worker mode: VideoMode::Fullscreen
1816*bb4ee6a4SAndroid Build Coastguard Worker }
1817*bb4ee6a4SAndroid Build Coastguard Worker );
1818*bb4ee6a4SAndroid Build Coastguard Worker
1819*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("mode=window-as-tuple[640,480]").unwrap();
1820*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1821*bb4ee6a4SAndroid Build Coastguard Worker res,
1822*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1823*bb4ee6a4SAndroid Build Coastguard Worker mode: VideoMode::WindowAsTuple(640, 480),
1824*bb4ee6a4SAndroid Build Coastguard Worker }
1825*bb4ee6a4SAndroid Build Coastguard Worker );
1826*bb4ee6a4SAndroid Build Coastguard Worker
1827*bb4ee6a4SAndroid Build Coastguard Worker // Missing values
1828*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<TestStruct>("mode=window-as-tuple").unwrap_err();
1829*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1830*bb4ee6a4SAndroid Build Coastguard Worker err,
1831*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1832*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedOpenBracket,
1833*bb4ee6a4SAndroid Build Coastguard Worker pos: 20,
1834*bb4ee6a4SAndroid Build Coastguard Worker }
1835*bb4ee6a4SAndroid Build Coastguard Worker );
1836*bb4ee6a4SAndroid Build Coastguard Worker
1837*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct =
1838*bb4ee6a4SAndroid Build Coastguard Worker from_key_values("mode=window-as-struct[width=800,height=600]").unwrap();
1839*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1840*bb4ee6a4SAndroid Build Coastguard Worker res,
1841*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1842*bb4ee6a4SAndroid Build Coastguard Worker mode: VideoMode::WindowAsStruct {
1843*bb4ee6a4SAndroid Build Coastguard Worker width: 800,
1844*bb4ee6a4SAndroid Build Coastguard Worker height: 600,
1845*bb4ee6a4SAndroid Build Coastguard Worker }
1846*bb4ee6a4SAndroid Build Coastguard Worker }
1847*bb4ee6a4SAndroid Build Coastguard Worker );
1848*bb4ee6a4SAndroid Build Coastguard Worker
1849*bb4ee6a4SAndroid Build Coastguard Worker // Missing values.
1850*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<TestStruct>("mode=window-as-struct").unwrap_err();
1851*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1852*bb4ee6a4SAndroid Build Coastguard Worker err,
1853*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1854*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedOpenBracket,
1855*bb4ee6a4SAndroid Build Coastguard Worker pos: 21,
1856*bb4ee6a4SAndroid Build Coastguard Worker }
1857*bb4ee6a4SAndroid Build Coastguard Worker );
1858*bb4ee6a4SAndroid Build Coastguard Worker }
1859*bb4ee6a4SAndroid Build Coastguard Worker
1860*bb4ee6a4SAndroid Build Coastguard Worker #[test]
deserialize_struct_enum_with_default()1861*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_struct_enum_with_default() {
1862*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1863*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
1864*bb4ee6a4SAndroid Build Coastguard Worker enum FlipMode {
1865*bb4ee6a4SAndroid Build Coastguard Worker Inactive,
1866*bb4ee6a4SAndroid Build Coastguard Worker Active {
1867*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1868*bb4ee6a4SAndroid Build Coastguard Worker switch1: bool,
1869*bb4ee6a4SAndroid Build Coastguard Worker #[serde(default)]
1870*bb4ee6a4SAndroid Build Coastguard Worker switch2: bool,
1871*bb4ee6a4SAndroid Build Coastguard Worker },
1872*bb4ee6a4SAndroid Build Coastguard Worker }
1873*bb4ee6a4SAndroid Build Coastguard Worker
1874*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Deserialize, PartialEq, Debug)]
1875*bb4ee6a4SAndroid Build Coastguard Worker struct TestStruct {
1876*bb4ee6a4SAndroid Build Coastguard Worker mode: FlipMode,
1877*bb4ee6a4SAndroid Build Coastguard Worker }
1878*bb4ee6a4SAndroid Build Coastguard Worker
1879*bb4ee6a4SAndroid Build Coastguard Worker // Only specify one member and expect the other to be default.
1880*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("mode=active[switch1=true]").unwrap();
1881*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1882*bb4ee6a4SAndroid Build Coastguard Worker res,
1883*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1884*bb4ee6a4SAndroid Build Coastguard Worker mode: FlipMode::Active {
1885*bb4ee6a4SAndroid Build Coastguard Worker switch1: true,
1886*bb4ee6a4SAndroid Build Coastguard Worker switch2: false
1887*bb4ee6a4SAndroid Build Coastguard Worker }
1888*bb4ee6a4SAndroid Build Coastguard Worker }
1889*bb4ee6a4SAndroid Build Coastguard Worker );
1890*bb4ee6a4SAndroid Build Coastguard Worker
1891*bb4ee6a4SAndroid Build Coastguard Worker // Specify boolean members without explicit value.
1892*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("mode=active[switch1,switch2]").unwrap();
1893*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1894*bb4ee6a4SAndroid Build Coastguard Worker res,
1895*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1896*bb4ee6a4SAndroid Build Coastguard Worker mode: FlipMode::Active {
1897*bb4ee6a4SAndroid Build Coastguard Worker switch1: true,
1898*bb4ee6a4SAndroid Build Coastguard Worker switch2: true
1899*bb4ee6a4SAndroid Build Coastguard Worker }
1900*bb4ee6a4SAndroid Build Coastguard Worker }
1901*bb4ee6a4SAndroid Build Coastguard Worker );
1902*bb4ee6a4SAndroid Build Coastguard Worker
1903*bb4ee6a4SAndroid Build Coastguard Worker // No member specified, braces present.
1904*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("mode=active[]").unwrap();
1905*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1906*bb4ee6a4SAndroid Build Coastguard Worker res,
1907*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1908*bb4ee6a4SAndroid Build Coastguard Worker mode: FlipMode::Active {
1909*bb4ee6a4SAndroid Build Coastguard Worker switch1: false,
1910*bb4ee6a4SAndroid Build Coastguard Worker switch2: false
1911*bb4ee6a4SAndroid Build Coastguard Worker }
1912*bb4ee6a4SAndroid Build Coastguard Worker }
1913*bb4ee6a4SAndroid Build Coastguard Worker );
1914*bb4ee6a4SAndroid Build Coastguard Worker
1915*bb4ee6a4SAndroid Build Coastguard Worker // No member specified and no braces.
1916*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("mode=active").unwrap();
1917*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1918*bb4ee6a4SAndroid Build Coastguard Worker res,
1919*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1920*bb4ee6a4SAndroid Build Coastguard Worker mode: FlipMode::Active {
1921*bb4ee6a4SAndroid Build Coastguard Worker switch1: false,
1922*bb4ee6a4SAndroid Build Coastguard Worker switch2: false
1923*bb4ee6a4SAndroid Build Coastguard Worker }
1924*bb4ee6a4SAndroid Build Coastguard Worker }
1925*bb4ee6a4SAndroid Build Coastguard Worker );
1926*bb4ee6a4SAndroid Build Coastguard Worker
1927*bb4ee6a4SAndroid Build Coastguard Worker // Non-struct variant should be recognized without braces.
1928*bb4ee6a4SAndroid Build Coastguard Worker let res: TestStruct = from_key_values("mode=inactive").unwrap();
1929*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1930*bb4ee6a4SAndroid Build Coastguard Worker res,
1931*bb4ee6a4SAndroid Build Coastguard Worker TestStruct {
1932*bb4ee6a4SAndroid Build Coastguard Worker mode: FlipMode::Inactive,
1933*bb4ee6a4SAndroid Build Coastguard Worker }
1934*bb4ee6a4SAndroid Build Coastguard Worker );
1935*bb4ee6a4SAndroid Build Coastguard Worker
1936*bb4ee6a4SAndroid Build Coastguard Worker // Non-struct variant should not accept braces.
1937*bb4ee6a4SAndroid Build Coastguard Worker let err = from_key_values::<TestStruct>("mode=inactive[]").unwrap_err();
1938*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
1939*bb4ee6a4SAndroid Build Coastguard Worker err,
1940*bb4ee6a4SAndroid Build Coastguard Worker ParseError {
1941*bb4ee6a4SAndroid Build Coastguard Worker kind: ErrorKind::ExpectedComma,
1942*bb4ee6a4SAndroid Build Coastguard Worker pos: 13,
1943*bb4ee6a4SAndroid Build Coastguard Worker }
1944*bb4ee6a4SAndroid Build Coastguard Worker );
1945*bb4ee6a4SAndroid Build Coastguard Worker }
1946*bb4ee6a4SAndroid Build Coastguard Worker }
1947