1extern crate alloc;
15
16use alloc::{borrow::Cow, string::String, vec::Vec};
17
18use crate::error::{XdrError, codes};
19use facet_format::{
20 ContainerKind, EnumVariantHint, FieldEvidence, FormatParser, ParseEvent, ProbeStream,
21 ScalarTypeHint, ScalarValue,
22};
23
24#[derive(Debug, Clone)]
26struct VariantMeta {
27 name: String,
28 kind: facet_core::StructKind,
29 field_count: usize,
30}
31
32#[derive(Debug, Clone)]
34enum ParserState {
35 Ready,
37 InStruct { remaining_fields: usize },
39 InSequence { remaining_elements: u32 },
41 InArray { remaining_elements: usize },
43 InEnum {
45 variant_name: String,
46 variant_kind: facet_core::StructKind,
47 variant_field_count: usize,
48 field_key_emitted: bool,
49 wrapper_start_emitted: bool,
50 wrapper_end_emitted: bool,
51 },
52}
53
54pub struct XdrParser<'de> {
59 input: &'de [u8],
60 pos: usize,
61 state_stack: Vec<ParserState>,
63 peeked: Option<ParseEvent<'de>>,
65 pending_struct_fields: Option<usize>,
67 pending_scalar_type: Option<ScalarTypeHint>,
69 pending_sequence: bool,
71 pending_array: Option<usize>,
73 pending_option: bool,
75 pending_enum: Option<Vec<VariantMeta>>,
77}
78
79impl<'de> XdrParser<'de> {
80 pub const fn new(input: &'de [u8]) -> Self {
82 Self {
83 input,
84 pos: 0,
85 state_stack: Vec::new(),
86 peeked: None,
87 pending_struct_fields: None,
88 pending_scalar_type: None,
89 pending_sequence: false,
90 pending_array: None,
91 pending_option: false,
92 pending_enum: None,
93 }
94 }
95
96 fn read_u32(&mut self) -> Result<u32, XdrError> {
98 if self.pos + 4 > self.input.len() {
99 return Err(XdrError::from_code(codes::UNEXPECTED_EOF, self.pos));
100 }
101 let bytes = &self.input[self.pos..self.pos + 4];
102 self.pos += 4;
103 Ok(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
104 }
105
106 fn read_u64(&mut self) -> Result<u64, XdrError> {
108 if self.pos + 8 > self.input.len() {
109 return Err(XdrError::from_code(codes::UNEXPECTED_EOF, self.pos));
110 }
111 let bytes = &self.input[self.pos..self.pos + 8];
112 self.pos += 8;
113 Ok(u64::from_be_bytes([
114 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
115 ]))
116 }
117
118 fn read_i32(&mut self) -> Result<i32, XdrError> {
120 Ok(self.read_u32()? as i32)
121 }
122
123 fn read_i64(&mut self) -> Result<i64, XdrError> {
125 Ok(self.read_u64()? as i64)
126 }
127
128 fn read_f32(&mut self) -> Result<f32, XdrError> {
130 let bits = self.read_u32()?;
131 Ok(f32::from_bits(bits))
132 }
133
134 fn read_f64(&mut self) -> Result<f64, XdrError> {
136 let bits = self.read_u64()?;
137 Ok(f64::from_bits(bits))
138 }
139
140 fn read_opaque_var(&mut self) -> Result<&'de [u8], XdrError> {
142 let len = self.read_u32()? as usize;
143 if self.pos + len > self.input.len() {
144 return Err(XdrError::from_code(codes::UNEXPECTED_EOF, self.pos));
145 }
146 let data = &self.input[self.pos..self.pos + len];
147 self.pos += len;
148 let pad = (4 - (len % 4)) % 4;
150 if self.pos + pad > self.input.len() {
151 return Err(XdrError::from_code(codes::UNEXPECTED_EOF, self.pos));
152 }
153 self.pos += pad;
154 Ok(data)
155 }
156
157 fn read_string(&mut self) -> Result<Cow<'de, str>, XdrError> {
159 let bytes = self.read_opaque_var()?;
160 core::str::from_utf8(bytes)
161 .map(Cow::Borrowed)
162 .map_err(|_| XdrError::from_code(codes::INVALID_UTF8, self.pos))
163 }
164
165 fn read_bool(&mut self) -> Result<bool, XdrError> {
167 let val = self.read_u32()?;
168 match val {
169 0 => Ok(false),
170 1 => Ok(true),
171 _ => Err(XdrError::from_code(codes::INVALID_BOOL, self.pos - 4)),
172 }
173 }
174
175 fn current_state(&self) -> &ParserState {
177 self.state_stack.last().unwrap_or(&ParserState::Ready)
178 }
179
180 fn generate_next_event(&mut self) -> Result<ParseEvent<'de>, XdrError> {
182 if self.pending_option {
184 self.pending_option = false;
185 let discriminant = self.read_u32()?;
186 match discriminant {
187 0 => return Ok(ParseEvent::Scalar(ScalarValue::Null)),
188 1 => {
189 return Ok(ParseEvent::OrderedField);
191 }
192 _ => {
193 return Err(XdrError::from_code(codes::INVALID_OPTIONAL, self.pos - 4));
194 }
195 }
196 }
197
198 if let Some(variants) = self.pending_enum.take() {
200 let discriminant = self.read_u32()? as usize;
201
202 if discriminant >= variants.len() {
203 return Err(XdrError::from_code(codes::INVALID_VARIANT, self.pos - 4));
204 }
205 let variant = &variants[discriminant];
206
207 self.state_stack.push(ParserState::InEnum {
208 variant_name: variant.name.clone(),
209 variant_kind: variant.kind,
210 variant_field_count: variant.field_count,
211 field_key_emitted: false,
212 wrapper_start_emitted: false,
213 wrapper_end_emitted: false,
214 });
215 return Ok(ParseEvent::StructStart(ContainerKind::Object));
216 }
217
218 if let Some(hint) = self.pending_scalar_type.take() {
220 return self.parse_scalar_with_hint(hint);
221 }
222
223 if self.pending_sequence {
225 self.pending_sequence = false;
226 let count = self.read_u32()?;
227 self.state_stack.push(ParserState::InSequence {
228 remaining_elements: count,
229 });
230 return Ok(ParseEvent::SequenceStart(ContainerKind::Array));
231 }
232
233 if let Some(len) = self.pending_array.take() {
235 self.state_stack.push(ParserState::InArray {
236 remaining_elements: len,
237 });
238 return Ok(ParseEvent::SequenceStart(ContainerKind::Array));
239 }
240
241 if let Some(num_fields) = self.pending_struct_fields.take() {
243 self.state_stack.push(ParserState::InStruct {
244 remaining_fields: num_fields,
245 });
246 return Ok(ParseEvent::StructStart(ContainerKind::Object));
247 }
248
249 match self.current_state().clone() {
251 ParserState::Ready => {
252 Err(XdrError::new(
254 codes::UNSUPPORTED_TYPE,
255 self.pos,
256 "XDR parser needs type hints (use hint_scalar_type, hint_struct_fields, or hint_sequence)",
257 ))
258 }
259 ParserState::InStruct { remaining_fields } => {
260 if remaining_fields == 0 {
261 self.state_stack.pop();
262 Ok(ParseEvent::StructEnd)
263 } else {
264 if let Some(ParserState::InStruct { remaining_fields }) =
265 self.state_stack.last_mut()
266 {
267 *remaining_fields -= 1;
268 }
269 Ok(ParseEvent::OrderedField)
270 }
271 }
272 ParserState::InSequence { remaining_elements } => {
273 if remaining_elements == 0 {
274 self.state_stack.pop();
275 Ok(ParseEvent::SequenceEnd)
276 } else {
277 if let Some(ParserState::InSequence { remaining_elements }) =
278 self.state_stack.last_mut()
279 {
280 *remaining_elements -= 1;
281 }
282 Ok(ParseEvent::OrderedField)
283 }
284 }
285 ParserState::InArray { remaining_elements } => {
286 if remaining_elements == 0 {
287 self.state_stack.pop();
288 Ok(ParseEvent::SequenceEnd)
289 } else {
290 if let Some(ParserState::InArray { remaining_elements }) =
291 self.state_stack.last_mut()
292 {
293 *remaining_elements -= 1;
294 }
295 Ok(ParseEvent::OrderedField)
296 }
297 }
298 ParserState::InEnum {
299 variant_name,
300 variant_kind,
301 variant_field_count,
302 field_key_emitted,
303 wrapper_start_emitted,
304 wrapper_end_emitted,
305 } => {
306 use facet_core::StructKind;
307
308 if !field_key_emitted {
309 if let Some(ParserState::InEnum {
310 field_key_emitted, ..
311 }) = self.state_stack.last_mut()
312 {
313 *field_key_emitted = true;
314 }
315 Ok(ParseEvent::FieldKey(facet_format::FieldKey::new(
316 Cow::Owned(variant_name),
317 facet_format::FieldLocationHint::KeyValue,
318 )))
319 } else if !wrapper_start_emitted {
320 match variant_kind {
321 StructKind::Unit => {
322 self.state_stack.pop();
323 Ok(ParseEvent::StructEnd)
324 }
325 StructKind::Tuple | StructKind::TupleStruct => {
326 if variant_field_count == 1 {
327 if let Some(ParserState::InEnum {
329 wrapper_start_emitted,
330 wrapper_end_emitted,
331 ..
332 }) = self.state_stack.last_mut()
333 {
334 *wrapper_start_emitted = true;
335 *wrapper_end_emitted = true;
336 }
337 self.generate_next_event()
338 } else {
339 if let Some(ParserState::InEnum {
340 wrapper_start_emitted,
341 ..
342 }) = self.state_stack.last_mut()
343 {
344 *wrapper_start_emitted = true;
345 }
346 Ok(ParseEvent::SequenceStart(ContainerKind::Array))
347 }
348 }
349 StructKind::Struct => {
350 if let Some(ParserState::InEnum {
351 wrapper_start_emitted,
352 ..
353 }) = self.state_stack.last_mut()
354 {
355 *wrapper_start_emitted = true;
356 }
357 self.state_stack.push(ParserState::InStruct {
358 remaining_fields: variant_field_count,
359 });
360 Ok(ParseEvent::StructStart(ContainerKind::Object))
361 }
362 }
363 } else if !wrapper_end_emitted {
364 match variant_kind {
365 StructKind::Unit => unreachable!(),
366 StructKind::Tuple | StructKind::TupleStruct => {
367 if variant_field_count > 1 {
368 if let Some(ParserState::InEnum {
369 wrapper_end_emitted,
370 ..
371 }) = self.state_stack.last_mut()
372 {
373 *wrapper_end_emitted = true;
374 }
375 Ok(ParseEvent::SequenceEnd)
376 } else {
377 self.state_stack.pop();
378 Ok(ParseEvent::StructEnd)
379 }
380 }
381 StructKind::Struct => {
382 self.state_stack.pop();
383 Ok(ParseEvent::StructEnd)
384 }
385 }
386 } else {
387 self.state_stack.pop();
388 Ok(ParseEvent::StructEnd)
389 }
390 }
391 }
392 }
393
394 fn parse_scalar_with_hint(
396 &mut self,
397 hint: ScalarTypeHint,
398 ) -> Result<ParseEvent<'de>, XdrError> {
399 let scalar = match hint {
400 ScalarTypeHint::Bool => {
401 let val = self.read_bool()?;
402 ScalarValue::Bool(val)
403 }
404 ScalarTypeHint::U8 => {
406 let val = self.read_u32()? as u8;
407 ScalarValue::U64(val as u64)
408 }
409 ScalarTypeHint::U16 => {
410 let val = self.read_u32()? as u16;
411 ScalarValue::U64(val as u64)
412 }
413 ScalarTypeHint::U32 => {
414 let val = self.read_u32()?;
415 ScalarValue::U64(val as u64)
416 }
417 ScalarTypeHint::U64 => {
418 let val = self.read_u64()?;
419 ScalarValue::U64(val)
420 }
421 ScalarTypeHint::U128 => {
422 return Err(XdrError::from_code(codes::UNSUPPORTED_TYPE, self.pos));
424 }
425 ScalarTypeHint::Usize => {
426 let val = self.read_u64()?;
428 ScalarValue::U64(val)
429 }
430 ScalarTypeHint::I8 => {
431 let val = self.read_i32()? as i8;
432 ScalarValue::I64(val as i64)
433 }
434 ScalarTypeHint::I16 => {
435 let val = self.read_i32()? as i16;
436 ScalarValue::I64(val as i64)
437 }
438 ScalarTypeHint::I32 => {
439 let val = self.read_i32()?;
440 ScalarValue::I64(val as i64)
441 }
442 ScalarTypeHint::I64 => {
443 let val = self.read_i64()?;
444 ScalarValue::I64(val)
445 }
446 ScalarTypeHint::I128 => {
447 return Err(XdrError::from_code(codes::UNSUPPORTED_TYPE, self.pos));
449 }
450 ScalarTypeHint::Isize => {
451 let val = self.read_i64()?;
453 ScalarValue::I64(val)
454 }
455 ScalarTypeHint::F32 => {
456 let val = self.read_f32()?;
457 ScalarValue::F64(val as f64)
458 }
459 ScalarTypeHint::F64 => {
460 let val = self.read_f64()?;
461 ScalarValue::F64(val)
462 }
463 ScalarTypeHint::String => {
464 let val = self.read_string()?;
465 ScalarValue::Str(val)
466 }
467 ScalarTypeHint::Bytes => {
468 let val = self.read_opaque_var()?;
469 ScalarValue::Bytes(Cow::Borrowed(val))
470 }
471 ScalarTypeHint::Char => {
472 let val = self.read_u32()?;
474 let c = char::from_u32(val).ok_or_else(|| {
475 XdrError::new(codes::INVALID_UTF8, self.pos - 4, "invalid char codepoint")
476 })?;
477 ScalarValue::Str(Cow::Owned(c.to_string()))
478 }
479 };
480 Ok(ParseEvent::Scalar(scalar))
481 }
482}
483
484impl<'de> FormatParser<'de> for XdrParser<'de> {
485 type Error = XdrError;
486 type Probe<'a>
487 = XdrProbe
488 where
489 Self: 'a;
490
491 fn next_event(&mut self) -> Result<Option<ParseEvent<'de>>, Self::Error> {
492 if let Some(event) = self.peeked.take() {
493 return Ok(Some(event));
494 }
495 Ok(Some(self.generate_next_event()?))
496 }
497
498 fn peek_event(&mut self) -> Result<Option<ParseEvent<'de>>, Self::Error> {
499 if self.peeked.is_none() {
500 self.peeked = Some(self.generate_next_event()?);
501 }
502 Ok(self.peeked.clone())
503 }
504
505 fn skip_value(&mut self) -> Result<(), Self::Error> {
506 Err(XdrError::new(
508 codes::UNSUPPORTED_TYPE,
509 self.pos,
510 "skip_value not supported for XDR (non-self-describing format)",
511 ))
512 }
513
514 fn begin_probe(&mut self) -> Result<Self::Probe<'_>, Self::Error> {
515 Ok(XdrProbe)
517 }
518
519 fn is_self_describing(&self) -> bool {
520 false
521 }
522
523 fn hint_struct_fields(&mut self, num_fields: usize) {
524 self.pending_struct_fields = Some(num_fields);
525 if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
526 self.peeked = None;
527 }
528 }
529
530 fn hint_scalar_type(&mut self, hint: ScalarTypeHint) {
531 self.pending_scalar_type = Some(hint);
532 if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
533 self.peeked = None;
534 }
535 }
536
537 fn hint_sequence(&mut self) {
538 self.pending_sequence = true;
539 if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
540 self.peeked = None;
541 }
542 }
543
544 fn hint_array(&mut self, len: usize) {
545 self.pending_array = Some(len);
546 if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
547 self.peeked = None;
548 }
549 }
550
551 fn hint_option(&mut self) {
552 self.pending_option = true;
553 if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
554 self.peeked = None;
555 }
556 }
557
558 fn hint_enum(&mut self, variants: &[EnumVariantHint]) {
559 let metas: Vec<VariantMeta> = variants
560 .iter()
561 .map(|v| VariantMeta {
562 name: v.name.to_string(),
563 kind: v.kind,
564 field_count: v.field_count,
565 })
566 .collect();
567 self.pending_enum = Some(metas);
568 if matches!(self.peeked, Some(ParseEvent::OrderedField)) {
569 self.peeked = None;
570 }
571 }
572}
573
574pub struct XdrProbe;
578
579impl<'de> ProbeStream<'de> for XdrProbe {
580 type Error = XdrError;
581
582 fn next(&mut self) -> Result<Option<FieldEvidence<'de>>, Self::Error> {
583 Ok(None)
585 }
586}