1extern crate alloc;
15
16use alloc::{borrow::Cow, string::String, vec::Vec};
17
18use crate::error::codes;
19use facet_format::{
20 ContainerKind, DeserializeErrorKind, EnumVariantHint, FormatParser, ParseError, ParseEvent,
21 ParseEventKind, SavePoint, ScalarTypeHint, ScalarValue,
22};
23use facet_reflect::Span;
24
25fn error_from_code(code: i32, pos: usize) -> ParseError {
27 let message = match code {
28 codes::UNEXPECTED_EOF => "unexpected end of input",
29 codes::INVALID_BOOL => "invalid boolean value (must be 0 or 1)",
30 codes::INVALID_OPTIONAL => "invalid optional discriminant (must be 0 or 1)",
31 codes::INVALID_VARIANT => "invalid enum discriminant",
32 codes::INVALID_UTF8 => "invalid UTF-8 in string",
33 codes::UNSUPPORTED_TYPE => "unsupported type for XDR",
34 codes::ALIGNMENT_ERROR => "position not aligned to 4 bytes",
35 _ => "unknown error",
36 };
37 ParseError::new(
38 Span::new(pos, 1),
39 DeserializeErrorKind::InvalidValue {
40 message: message.into(),
41 },
42 )
43}
44
45#[derive(Debug, Clone)]
47struct VariantMeta {
48 name: String,
49 kind: facet_core::StructKind,
50 field_count: usize,
51}
52
53#[derive(Debug, Clone)]
55enum ParserState {
56 Ready,
58 InStruct { remaining_fields: usize },
60 InSequence { remaining_elements: u32 },
62 InArray { remaining_elements: usize },
64 InEnum {
66 variant_name: String,
67 variant_kind: facet_core::StructKind,
68 variant_field_count: usize,
69 field_key_emitted: bool,
70 wrapper_start_emitted: bool,
71 wrapper_end_emitted: bool,
72 },
73}
74
75pub struct XdrParser<'de> {
80 input: &'de [u8],
81 pos: usize,
82 state_stack: Vec<ParserState>,
84 peeked: Option<ParseEvent<'de>>,
86 pending_struct_fields: Option<usize>,
88 pending_scalar_type: Option<ScalarTypeHint>,
90 pending_sequence: bool,
92 pending_array: Option<usize>,
94 pending_option: bool,
96 pending_enum: Option<Vec<VariantMeta>>,
98}
99
100impl<'de> XdrParser<'de> {
101 pub const fn new(input: &'de [u8]) -> Self {
103 Self {
104 input,
105 pos: 0,
106 state_stack: Vec::new(),
107 peeked: None,
108 pending_struct_fields: None,
109 pending_scalar_type: None,
110 pending_sequence: false,
111 pending_array: None,
112 pending_option: false,
113 pending_enum: None,
114 }
115 }
116
117 fn read_u32(&mut self) -> Result<u32, ParseError> {
119 if self.pos + 4 > self.input.len() {
120 return Err(error_from_code(codes::UNEXPECTED_EOF, self.pos));
121 }
122 let bytes = &self.input[self.pos..self.pos + 4];
123 self.pos += 4;
124 Ok(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
125 }
126
127 fn read_u64(&mut self) -> Result<u64, ParseError> {
129 if self.pos + 8 > self.input.len() {
130 return Err(error_from_code(codes::UNEXPECTED_EOF, self.pos));
131 }
132 let bytes = &self.input[self.pos..self.pos + 8];
133 self.pos += 8;
134 Ok(u64::from_be_bytes([
135 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
136 ]))
137 }
138
139 fn read_i32(&mut self) -> Result<i32, ParseError> {
141 Ok(self.read_u32()? as i32)
142 }
143
144 fn read_i64(&mut self) -> Result<i64, ParseError> {
146 Ok(self.read_u64()? as i64)
147 }
148
149 fn read_f32(&mut self) -> Result<f32, ParseError> {
151 let bits = self.read_u32()?;
152 Ok(f32::from_bits(bits))
153 }
154
155 fn read_f64(&mut self) -> Result<f64, ParseError> {
157 let bits = self.read_u64()?;
158 Ok(f64::from_bits(bits))
159 }
160
161 fn read_opaque_var(&mut self) -> Result<&'de [u8], ParseError> {
163 let len = self.read_u32()? as usize;
164 if self.pos + len > self.input.len() {
165 return Err(error_from_code(codes::UNEXPECTED_EOF, self.pos));
166 }
167 let data = &self.input[self.pos..self.pos + len];
168 self.pos += len;
169 let pad = (4 - (len % 4)) % 4;
171 if self.pos + pad > self.input.len() {
172 return Err(error_from_code(codes::UNEXPECTED_EOF, self.pos));
173 }
174 self.pos += pad;
175 Ok(data)
176 }
177
178 fn read_string(&mut self) -> Result<Cow<'de, str>, ParseError> {
180 let start_pos = self.pos;
181 let bytes = self.read_opaque_var()?;
182 core::str::from_utf8(bytes).map(Cow::Borrowed).map_err(|_| {
183 let mut context = [0u8; 16];
184 let context_len = bytes.len().min(16);
185 context[..context_len].copy_from_slice(&bytes[..context_len]);
186 ParseError::new(
187 Span::new(start_pos, bytes.len()),
188 DeserializeErrorKind::InvalidUtf8 {
189 context,
190 context_len: context_len as u8,
191 },
192 )
193 })
194 }
195
196 fn read_bool(&mut self) -> Result<bool, ParseError> {
198 let val = self.read_u32()?;
199 match val {
200 0 => Ok(false),
201 1 => Ok(true),
202 _ => Err(error_from_code(codes::INVALID_BOOL, self.pos - 4)),
203 }
204 }
205
206 fn current_state(&self) -> &ParserState {
208 self.state_stack.last().unwrap_or(&ParserState::Ready)
209 }
210
211 fn generate_next_event(&mut self) -> Result<ParseEvent<'de>, ParseError> {
213 if self.pending_option {
215 self.pending_option = false;
216 let discriminant = self.read_u32()?;
217 match discriminant {
218 0 => {
219 return Ok(self.event(ParseEventKind::Scalar(ScalarValue::Null)));
220 }
221 1 => {
222 return Ok(self.event(ParseEventKind::OrderedField));
224 }
225 _ => {
226 return Err(error_from_code(codes::INVALID_OPTIONAL, self.pos - 4));
227 }
228 }
229 }
230
231 if let Some(variants) = self.pending_enum.take() {
233 let discriminant = self.read_u32()? as usize;
234
235 if discriminant >= variants.len() {
236 return Err(error_from_code(codes::INVALID_VARIANT, self.pos - 4));
237 }
238 let variant = &variants[discriminant];
239
240 self.state_stack.push(ParserState::InEnum {
241 variant_name: variant.name.clone(),
242 variant_kind: variant.kind,
243 variant_field_count: variant.field_count,
244 field_key_emitted: false,
245 wrapper_start_emitted: false,
246 wrapper_end_emitted: false,
247 });
248 return Ok(self.event(ParseEventKind::StructStart(ContainerKind::Object)));
249 }
250
251 if let Some(hint) = self.pending_scalar_type.take() {
253 return self.parse_scalar_with_hint(hint);
254 }
255
256 if self.pending_sequence {
258 self.pending_sequence = false;
259 let count = self.read_u32()?;
260 self.state_stack.push(ParserState::InSequence {
261 remaining_elements: count,
262 });
263 return Ok(self.event(ParseEventKind::SequenceStart(ContainerKind::Array)));
264 }
265
266 if let Some(len) = self.pending_array.take() {
268 self.state_stack.push(ParserState::InArray {
269 remaining_elements: len,
270 });
271 return Ok(self.event(ParseEventKind::SequenceStart(ContainerKind::Array)));
272 }
273
274 if let Some(num_fields) = self.pending_struct_fields.take() {
276 self.state_stack.push(ParserState::InStruct {
277 remaining_fields: num_fields,
278 });
279 return Ok(self.event(ParseEventKind::StructStart(ContainerKind::Object)));
280 }
281
282 match self.current_state().clone() {
284 ParserState::Ready => {
285 Err(ParseError::new(
287 Span::new(self.pos, 1),
288 DeserializeErrorKind::InvalidValue {
289 message: "XDR parser needs type hints (use hint_scalar_type, hint_struct_fields, or hint_sequence)".into(),
290 },
291 ))
292 }
293 ParserState::InStruct { remaining_fields } => {
294 if remaining_fields == 0 {
295 self.state_stack.pop();
296 Ok(self.event(ParseEventKind::StructEnd))
297 } else {
298 if let Some(ParserState::InStruct { remaining_fields }) =
299 self.state_stack.last_mut()
300 {
301 *remaining_fields -= 1;
302 }
303 Ok(self.event(ParseEventKind::OrderedField))
304 }
305 }
306 ParserState::InSequence { remaining_elements } => {
307 if remaining_elements == 0 {
308 self.state_stack.pop();
309 Ok(self.event(ParseEventKind::SequenceEnd))
310 } else {
311 if let Some(ParserState::InSequence { remaining_elements }) =
312 self.state_stack.last_mut()
313 {
314 *remaining_elements -= 1;
315 }
316 Ok(self.event(ParseEventKind::OrderedField))
317 }
318 }
319 ParserState::InArray { remaining_elements } => {
320 if remaining_elements == 0 {
321 self.state_stack.pop();
322 Ok(self.event(ParseEventKind::SequenceEnd))
323 } else {
324 if let Some(ParserState::InArray { remaining_elements }) =
325 self.state_stack.last_mut()
326 {
327 *remaining_elements -= 1;
328 }
329 Ok(self.event(ParseEventKind::OrderedField))
330 }
331 }
332 ParserState::InEnum {
333 variant_name,
334 variant_kind,
335 variant_field_count,
336 field_key_emitted,
337 wrapper_start_emitted,
338 wrapper_end_emitted,
339 } => {
340 use facet_core::StructKind;
341
342 if !field_key_emitted {
343 if let Some(ParserState::InEnum {
344 field_key_emitted, ..
345 }) = self.state_stack.last_mut()
346 {
347 *field_key_emitted = true;
348 }
349 Ok(
350 self.event(ParseEventKind::FieldKey(facet_format::FieldKey::new(
351 Cow::Owned(variant_name),
352 facet_format::FieldLocationHint::KeyValue,
353 ))),
354 )
355 } else if !wrapper_start_emitted {
356 match variant_kind {
357 StructKind::Unit => {
358 self.state_stack.pop();
359 Ok(self.event(ParseEventKind::StructEnd))
360 }
361 StructKind::Tuple | StructKind::TupleStruct => {
362 if variant_field_count == 1 {
363 if let Some(ParserState::InEnum {
365 wrapper_start_emitted,
366 wrapper_end_emitted,
367 ..
368 }) = self.state_stack.last_mut()
369 {
370 *wrapper_start_emitted = true;
371 *wrapper_end_emitted = true;
372 }
373 self.generate_next_event()
374 } else {
375 if let Some(ParserState::InEnum {
376 wrapper_start_emitted,
377 ..
378 }) = self.state_stack.last_mut()
379 {
380 *wrapper_start_emitted = true;
381 }
382 Ok(self.event(ParseEventKind::SequenceStart(ContainerKind::Array)))
383 }
384 }
385 StructKind::Struct => {
386 if let Some(ParserState::InEnum {
387 wrapper_start_emitted,
388 ..
389 }) = self.state_stack.last_mut()
390 {
391 *wrapper_start_emitted = true;
392 }
393 self.state_stack.push(ParserState::InStruct {
394 remaining_fields: variant_field_count,
395 });
396 Ok(self.event(ParseEventKind::StructStart(ContainerKind::Object)))
397 }
398 }
399 } else if !wrapper_end_emitted {
400 match variant_kind {
401 StructKind::Unit => unreachable!(),
402 StructKind::Tuple | StructKind::TupleStruct => {
403 if variant_field_count > 1 {
404 if let Some(ParserState::InEnum {
405 wrapper_end_emitted,
406 ..
407 }) = self.state_stack.last_mut()
408 {
409 *wrapper_end_emitted = true;
410 }
411 Ok(self.event(ParseEventKind::SequenceEnd))
412 } else {
413 self.state_stack.pop();
414 Ok(self.event(ParseEventKind::StructEnd))
415 }
416 }
417 StructKind::Struct => {
418 self.state_stack.pop();
419 Ok(self.event(ParseEventKind::StructEnd))
420 }
421 }
422 } else {
423 self.state_stack.pop();
424 Ok(self.event(ParseEventKind::StructEnd))
425 }
426 }
427 }
428 }
429
430 fn parse_scalar_with_hint(
432 &mut self,
433 hint: ScalarTypeHint,
434 ) -> Result<ParseEvent<'de>, ParseError> {
435 let scalar = match hint {
436 ScalarTypeHint::Bool => {
437 let val = self.read_bool()?;
438 ScalarValue::Bool(val)
439 }
440 ScalarTypeHint::U8 => {
442 let val = self.read_u32()? as u8;
443 ScalarValue::U64(val as u64)
444 }
445 ScalarTypeHint::U16 => {
446 let val = self.read_u32()? as u16;
447 ScalarValue::U64(val as u64)
448 }
449 ScalarTypeHint::U32 => {
450 let val = self.read_u32()?;
451 ScalarValue::U64(val as u64)
452 }
453 ScalarTypeHint::U64 => {
454 let val = self.read_u64()?;
455 ScalarValue::U64(val)
456 }
457 ScalarTypeHint::U128 => {
458 return Err(error_from_code(codes::UNSUPPORTED_TYPE, self.pos));
460 }
461 ScalarTypeHint::Usize => {
462 let val = self.read_u64()?;
464 ScalarValue::U64(val)
465 }
466 ScalarTypeHint::I8 => {
467 let val = self.read_i32()? as i8;
468 ScalarValue::I64(val as i64)
469 }
470 ScalarTypeHint::I16 => {
471 let val = self.read_i32()? as i16;
472 ScalarValue::I64(val as i64)
473 }
474 ScalarTypeHint::I32 => {
475 let val = self.read_i32()?;
476 ScalarValue::I64(val as i64)
477 }
478 ScalarTypeHint::I64 => {
479 let val = self.read_i64()?;
480 ScalarValue::I64(val)
481 }
482 ScalarTypeHint::I128 => {
483 return Err(error_from_code(codes::UNSUPPORTED_TYPE, self.pos));
485 }
486 ScalarTypeHint::Isize => {
487 let val = self.read_i64()?;
489 ScalarValue::I64(val)
490 }
491 ScalarTypeHint::F32 => {
492 let val = self.read_f32()?;
493 ScalarValue::F64(val as f64)
494 }
495 ScalarTypeHint::F64 => {
496 let val = self.read_f64()?;
497 ScalarValue::F64(val)
498 }
499 ScalarTypeHint::String => {
500 let val = self.read_string()?;
501 ScalarValue::Str(val)
502 }
503 ScalarTypeHint::Bytes => {
504 let val = self.read_opaque_var()?;
505 ScalarValue::Bytes(Cow::Borrowed(val))
506 }
507 ScalarTypeHint::Char => {
508 let val = self.read_u32()?;
510 let c = char::from_u32(val).ok_or_else(|| {
511 ParseError::new(
512 Span::new(self.pos - 4, 4),
513 DeserializeErrorKind::InvalidValue {
514 message: "invalid char codepoint".into(),
515 },
516 )
517 })?;
518 ScalarValue::Str(Cow::Owned(c.to_string()))
519 }
520 };
521 Ok(self.event(ParseEventKind::Scalar(scalar)))
522 }
523}
524
525impl<'de> FormatParser<'de> for XdrParser<'de> {
526 fn next_event(&mut self) -> Result<Option<ParseEvent<'de>>, ParseError> {
527 if let Some(event) = self.peeked.take() {
528 return Ok(Some(event));
529 }
530 Ok(Some(self.generate_next_event()?))
531 }
532
533 fn peek_event(&mut self) -> Result<Option<ParseEvent<'de>>, ParseError> {
534 if self.peeked.is_none() {
535 self.peeked = Some(self.generate_next_event()?);
536 }
537 Ok(self.peeked.clone())
538 }
539
540 fn skip_value(&mut self) -> Result<(), ParseError> {
541 Err(ParseError::new(
543 Span::new(self.pos, 1),
544 DeserializeErrorKind::InvalidValue {
545 message: "skip_value not supported for XDR (non-self-describing format)".into(),
546 },
547 ))
548 }
549
550 fn current_span(&self) -> Option<Span> {
551 Some(Span::new(self.pos, 1))
552 }
553
554 fn save(&mut self) -> SavePoint {
555 unimplemented!("save/restore not supported for XDR (positional format)")
557 }
558
559 fn restore(&mut self, _save_point: SavePoint) {
560 unimplemented!("save/restore not supported for XDR (positional format)")
561 }
562
563 fn is_self_describing(&self) -> bool {
564 false
565 }
566
567 fn hint_struct_fields(&mut self, num_fields: usize) {
568 self.pending_struct_fields = Some(num_fields);
569 if self
570 .peeked
571 .as_ref()
572 .is_some_and(|e| matches!(e.kind, ParseEventKind::OrderedField))
573 {
574 self.peeked = None;
575 }
576 }
577
578 fn hint_scalar_type(&mut self, hint: ScalarTypeHint) {
579 self.pending_scalar_type = Some(hint);
580 if self
581 .peeked
582 .as_ref()
583 .is_some_and(|e| matches!(e.kind, ParseEventKind::OrderedField))
584 {
585 self.peeked = None;
586 }
587 }
588
589 fn hint_sequence(&mut self) {
590 self.pending_sequence = true;
591 if self
592 .peeked
593 .as_ref()
594 .is_some_and(|e| matches!(e.kind, ParseEventKind::OrderedField))
595 {
596 self.peeked = None;
597 }
598 }
599
600 fn hint_array(&mut self, len: usize) {
601 self.pending_array = Some(len);
602 if self
603 .peeked
604 .as_ref()
605 .is_some_and(|e| matches!(e.kind, ParseEventKind::OrderedField))
606 {
607 self.peeked = None;
608 }
609 }
610
611 fn hint_option(&mut self) {
612 self.pending_option = true;
613 if self
614 .peeked
615 .as_ref()
616 .is_some_and(|e| matches!(e.kind, ParseEventKind::OrderedField))
617 {
618 self.peeked = None;
619 }
620 }
621
622 fn hint_enum(&mut self, variants: &[EnumVariantHint]) {
623 let metas: Vec<VariantMeta> = variants
624 .iter()
625 .map(|v| VariantMeta {
626 name: v.name.to_string(),
627 kind: v.kind,
628 field_count: v.field_count,
629 })
630 .collect();
631 self.pending_enum = Some(metas);
632 if self
633 .peeked
634 .as_ref()
635 .is_some_and(|e| matches!(e.kind, ParseEventKind::OrderedField))
636 {
637 self.peeked = None;
638 }
639 }
640}
641
642impl<'de> XdrParser<'de> {
643 #[inline]
645 fn event(&self, kind: ParseEventKind<'de>) -> ParseEvent<'de> {
646 ParseEvent::new(kind, Span::new(self.pos, 1))
647 }
648}