1use std::{borrow::Cow, mem};
2
3use form_urlencoded::{Serializer as UrlEncodedSerializer, Target as UrlEncodedTarget};
4use serde::ser;
5
6use crate::ser::{key::KeySink, part::PartSerializer, value::ValueSink, Error};
7
8pub struct PairSerializer<'input, 'target, Target: UrlEncodedTarget> {
9 urlencoder: &'target mut UrlEncodedSerializer<'input, Target>,
10 state: PairState,
11}
12
13impl<'input, 'target, Target> PairSerializer<'input, 'target, Target>
14where
15 Target: 'target + UrlEncodedTarget,
16{
17 pub fn new(urlencoder: &'target mut UrlEncodedSerializer<'input, Target>) -> Self {
18 PairSerializer { urlencoder, state: PairState::WaitingForKey }
19 }
20}
21
22impl<'target, Target> ser::Serializer for PairSerializer<'_, 'target, Target>
23where
24 Target: 'target + UrlEncodedTarget,
25{
26 type Ok = ();
27 type Error = Error;
28 type SerializeSeq = ser::Impossible<(), Error>;
29 type SerializeTuple = Self;
30 type SerializeTupleStruct = ser::Impossible<(), Error>;
31 type SerializeTupleVariant = ser::Impossible<(), Error>;
32 type SerializeMap = ser::Impossible<(), Error>;
33 type SerializeStruct = ser::Impossible<(), Error>;
34 type SerializeStructVariant = ser::Impossible<(), Error>;
35
36 fn serialize_bool(self, _v: bool) -> Result<(), Error> {
37 Err(Error::unsupported_pair())
38 }
39
40 fn serialize_i8(self, _v: i8) -> Result<(), Error> {
41 Err(Error::unsupported_pair())
42 }
43
44 fn serialize_i16(self, _v: i16) -> Result<(), Error> {
45 Err(Error::unsupported_pair())
46 }
47
48 fn serialize_i32(self, _v: i32) -> Result<(), Error> {
49 Err(Error::unsupported_pair())
50 }
51
52 fn serialize_i64(self, _v: i64) -> Result<(), Error> {
53 Err(Error::unsupported_pair())
54 }
55
56 fn serialize_u8(self, _v: u8) -> Result<(), Error> {
57 Err(Error::unsupported_pair())
58 }
59
60 fn serialize_u16(self, _v: u16) -> Result<(), Error> {
61 Err(Error::unsupported_pair())
62 }
63
64 fn serialize_u32(self, _v: u32) -> Result<(), Error> {
65 Err(Error::unsupported_pair())
66 }
67
68 fn serialize_u64(self, _v: u64) -> Result<(), Error> {
69 Err(Error::unsupported_pair())
70 }
71
72 fn serialize_f32(self, _v: f32) -> Result<(), Error> {
73 Err(Error::unsupported_pair())
74 }
75
76 fn serialize_f64(self, _v: f64) -> Result<(), Error> {
77 Err(Error::unsupported_pair())
78 }
79
80 fn serialize_char(self, _v: char) -> Result<(), Error> {
81 Err(Error::unsupported_pair())
82 }
83
84 fn serialize_str(self, _value: &str) -> Result<(), Error> {
85 Err(Error::unsupported_pair())
86 }
87
88 fn serialize_bytes(self, _value: &[u8]) -> Result<(), Error> {
89 Err(Error::unsupported_pair())
90 }
91
92 fn serialize_unit(self) -> Result<(), Error> {
93 Err(Error::unsupported_pair())
94 }
95
96 fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Error> {
97 Err(Error::unsupported_pair())
98 }
99
100 fn serialize_unit_variant(
101 self,
102 _name: &'static str,
103 _variant_index: u32,
104 _variant: &'static str,
105 ) -> Result<(), Error> {
106 Err(Error::unsupported_pair())
107 }
108
109 fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
110 self,
111 _name: &'static str,
112 value: &T,
113 ) -> Result<(), Error> {
114 value.serialize(self)
115 }
116
117 fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
118 self,
119 _name: &'static str,
120 _variant_index: u32,
121 _variant: &'static str,
122 _value: &T,
123 ) -> Result<(), Error> {
124 Err(Error::unsupported_pair())
125 }
126
127 fn serialize_none(self) -> Result<(), Error> {
128 Ok(())
129 }
130
131 fn serialize_some<T: ?Sized + ser::Serialize>(self, value: &T) -> Result<(), Error> {
132 value.serialize(self)
133 }
134
135 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
136 Err(Error::unsupported_pair())
137 }
138
139 fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
140 if len == 2 {
141 Ok(self)
142 } else {
143 Err(Error::unsupported_pair())
144 }
145 }
146
147 fn serialize_tuple_struct(
148 self,
149 _name: &'static str,
150 _len: usize,
151 ) -> Result<Self::SerializeTupleStruct, Error> {
152 Err(Error::unsupported_pair())
153 }
154
155 fn serialize_tuple_variant(
156 self,
157 _name: &'static str,
158 _variant_index: u32,
159 _variant: &'static str,
160 _len: usize,
161 ) -> Result<Self::SerializeTupleVariant, Error> {
162 Err(Error::unsupported_pair())
163 }
164
165 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
166 Err(Error::unsupported_pair())
167 }
168
169 fn serialize_struct(
170 self,
171 _name: &'static str,
172 _len: usize,
173 ) -> Result<Self::SerializeStruct, Error> {
174 Err(Error::unsupported_pair())
175 }
176
177 fn serialize_struct_variant(
178 self,
179 _name: &'static str,
180 _variant_index: u32,
181 _variant: &'static str,
182 _len: usize,
183 ) -> Result<Self::SerializeStructVariant, Error> {
184 Err(Error::unsupported_pair())
185 }
186}
187
188impl<'target, Target> ser::SerializeTuple for PairSerializer<'_, 'target, Target>
189where
190 Target: 'target + UrlEncodedTarget,
191{
192 type Ok = ();
193 type Error = Error;
194
195 fn serialize_element<T: ?Sized + ser::Serialize>(&mut self, value: &T) -> Result<(), Error> {
196 match mem::replace(&mut self.state, PairState::Done) {
197 PairState::WaitingForKey => {
198 let key_sink = KeySink::new(|key| Ok(key.into()));
199 let key_serializer = PartSerializer::new(key_sink);
200 self.state = PairState::WaitingForValue { key: value.serialize(key_serializer)? };
201 Ok(())
202 }
203 PairState::WaitingForValue { key } => {
204 let result = {
205 let value_sink = ValueSink::new(self.urlencoder, &key);
206 let value_serializer = PartSerializer::new(value_sink);
207 value.serialize(value_serializer)
208 };
209 if result.is_ok() {
210 self.state = PairState::Done;
211 } else {
212 self.state = PairState::WaitingForValue { key };
213 }
214 result
215 }
216 PairState::Done => Err(Error::done()),
217 }
218 }
219
220 fn end(self) -> Result<(), Error> {
221 if let PairState::Done = self.state {
222 Ok(())
223 } else {
224 Err(Error::not_done())
225 }
226 }
227}
228
229enum PairState {
230 WaitingForKey,
231 WaitingForValue { key: Cow<'static, str> },
232 Done,
233}