1use super::error::{ProtocolError, ProtocolResult};
49use std::fmt;
50use std::io::{self, Read, Write};
51use std::str::FromStr;
52
53pub const BINARY_VERSION_1: u8 = 0x10;
56
57const FLAG_EXTERNAL_REFERENCES: u8 = 0b0001;
58const FLAG_EXPLICIT_LAYOUT: u8 = 0b0010;
59const WIDTH_SHIFT: u8 = 2;
60const WIDTH_BITS: u8 = 0b1100;
61
62const SHAPE_WIDTH_BITS: u64 = 0b0011;
63const SHAPE_HAS_GAP: u64 = 0b0100;
64const SHAPE_VARIABLE_ARITY: u64 = 0b1000;
65const SHAPE_MIN_ARITY_SHIFT: u32 = 4;
66
67pub const NULL: u64 = 0;
69pub const ONE: u64 = 1;
71pub const NUMBER: u64 = 2;
73pub const STRING: u64 = 3;
75pub const LIST: u64 = 4;
77pub const IDENTIFIED: u64 = 5;
79pub const FIRST_LINK_ADDRESS: u64 = 6;
81
82const COMPACT_GAP: u64 = FIRST_LINK_ADDRESS - 1;
84
85pub const WIDTHS: [u8; 4] = [1, 2, 4, 8];
87
88#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
90pub enum Reference {
91 Internal(u64),
93 External(u64),
95}
96
97impl Reference {
98 pub const NULL: Reference = Reference::Internal(NULL);
100}
101
102#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
105pub struct ArityRange {
106 pub min: u64,
108 pub max: Option<u64>,
110}
111
112impl ArityRange {
113 pub const DOUBLETS: ArityRange = ArityRange::exactly(2);
115
116 pub const fn exactly(arity: u64) -> Self {
118 Self {
119 min: arity,
120 max: Some(arity),
121 }
122 }
123
124 pub const fn at_least(min: u64) -> Self {
126 Self { min, max: None }
127 }
128
129 pub const fn between(min: u64, max: u64) -> Self {
131 Self {
132 min,
133 max: Some(max),
134 }
135 }
136
137 pub fn contains(&self, length: u64) -> bool {
139 length >= self.min && self.max.is_none_or(|max| length <= max)
140 }
141
142 pub fn is_fixed(&self) -> bool {
145 self.max == Some(self.min)
146 }
147
148 fn validate(&self) -> Result<(), String> {
149 if self.min == 0 {
150 return Err("arity must be at least 1".into());
151 }
152 if self.min > u64::MAX >> SHAPE_MIN_ARITY_SHIFT {
153 return Err(format!("arity {} is too large", self.min));
154 }
155 if self.max.is_some_and(|max| max < self.min) {
156 return Err(format!("arity range {self} is empty"));
157 }
158 Ok(())
159 }
160
161 fn extra(&self) -> u64 {
163 self.max.map_or(0, |max| max - self.min)
164 }
165
166 fn from_shape(min: u64, extra: Option<u64>) -> ProtocolResult<Self> {
167 let range = match extra {
168 None => Self::exactly(min),
169 Some(0) => Self::at_least(min),
170 Some(extra) => Self::between(
171 min,
172 min.checked_add(extra)
173 .ok_or_else(|| ProtocolError::malformed("arity range overflows 64 bits"))?,
174 ),
175 };
176 range.validate().map_err(ProtocolError::malformed)?;
177 Ok(range)
178 }
179}
180
181impl Default for ArityRange {
182 fn default() -> Self {
183 Self::DOUBLETS
184 }
185}
186
187impl fmt::Display for ArityRange {
188 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
189 match self.max {
190 Some(max) if max == self.min => write!(formatter, "{max}"),
191 Some(max) => write!(formatter, "{}..{max}", self.min),
192 None => write!(formatter, "{}..", self.min),
193 }
194 }
195}
196
197impl FromStr for ArityRange {
198 type Err = String;
199
200 fn from_str(text: &str) -> Result<Self, Self::Err> {
202 let number = |part: &str| {
203 part.parse::<u64>()
204 .map_err(|_| format!("invalid arity '{text}': expected n, min..max or min.."))
205 };
206 let range = match text.split_once("..") {
207 None => Self::exactly(number(text)?),
208 Some((min, "")) => Self::at_least(number(min)?),
209 Some((min, max)) => Self::between(number(min)?, number(max)?),
210 };
211 range.validate()?;
212 Ok(range)
213 }
214}
215
216#[derive(Clone, Copy, Debug, PartialEq, Eq)]
218pub struct DecodeLimits {
219 pub max_links: u64,
221 pub max_references: u64,
223 pub max_nodes: usize,
225 pub max_depth: usize,
227 pub max_text_bytes: usize,
229}
230
231impl Default for DecodeLimits {
232 fn default() -> Self {
233 Self {
234 max_links: 1 << 22,
235 max_references: 1 << 24,
236 max_nodes: 1 << 22,
237 max_depth: 1024,
238 max_text_bytes: 64 << 20,
239 }
240 }
241}
242
243impl DecodeLimits {
244 pub fn unlimited() -> Self {
247 Self {
248 max_links: u64::MAX,
249 max_references: u64::MAX,
250 max_nodes: usize::MAX,
251 max_depth: usize::MAX,
252 max_text_bytes: usize::MAX,
253 }
254 }
255}
256
257#[derive(Clone, Debug, PartialEq, Eq)]
260pub struct Section {
261 pub gap: u64,
263 pub arity: ArityRange,
265 pub width: u8,
267 pub links: Vec<Vec<Reference>>,
269}
270
271#[derive(Clone, Debug, Default, PartialEq, Eq)]
273pub struct LinksPacket {
274 pub external_references: bool,
276 pub sections: Vec<Section>,
278}
279
280pub fn internal_capacity(width: u8, external_references: bool) -> u64 {
282 let bits = u32::from(width) * 8 - u32::from(external_references);
283 if bits >= 64 {
284 u64::MAX
285 } else {
286 (1u64 << bits) - 1
287 }
288}
289
290pub fn external_capacity(width: u8) -> u64 {
292 (1u64 << (u32::from(width) * 8 - 1)) - 1
293}
294
295pub fn address_tier(address: u64, external_references: bool) -> ProtocolResult<u8> {
297 WIDTHS
298 .into_iter()
299 .find(|&width| internal_capacity(width, external_references) >= address)
300 .ok_or_else(|| {
301 ProtocolError::Unencodable(format!("address {address} exceeds the internal range"))
302 })
303}
304
305fn width_mask(width: u8) -> u64 {
306 internal_capacity(width, false)
307}
308
309pub fn encode_external(value: u64, width: u8) -> u64 {
311 if value == 0 {
312 1u64 << (u32::from(width) * 8 - 1)
313 } else {
314 value.wrapping_neg() & width_mask(width)
315 }
316}
317
318pub fn decode_external(raw: u64, width: u8) -> Option<u64> {
320 let external_zero = 1u64 << (u32::from(width) * 8 - 1);
321 if raw == external_zero {
322 Some(0)
323 } else if raw > external_zero {
324 Some(raw.wrapping_neg() & width_mask(width))
325 } else {
326 None
327 }
328}
329
330fn width_code(width: u8) -> ProtocolResult<u8> {
331 WIDTHS
332 .iter()
333 .position(|&candidate| candidate == width)
334 .map(|code| code as u8)
335 .ok_or_else(|| ProtocolError::Unencodable(format!("invalid width {width}")))
336}
337
338fn width_from_code(code: u64) -> u8 {
340 WIDTHS[(code & 0b11) as usize]
341}
342
343pub fn reference_width(reference: Reference, external_references: bool) -> ProtocolResult<u8> {
345 match reference {
346 Reference::Internal(address) => address_tier(address, external_references),
347 Reference::External(value) => {
348 if !external_references {
349 return Err(ProtocolError::Unencodable(
350 "external reference in a packet without external references".into(),
351 ));
352 }
353 WIDTHS
354 .into_iter()
355 .find(|&width| external_capacity(width) >= value)
356 .ok_or_else(|| {
357 ProtocolError::Unencodable(format!("external value {value} exceeds 63 bits"))
358 })
359 }
360 }
361}
362
363impl Section {
364 fn write_header(&self, out: &mut Vec<u8>) -> ProtocolResult<()> {
365 let mut shape =
366 u64::from(width_code(self.width)?) | (self.arity.min << SHAPE_MIN_ARITY_SHIFT);
367 if self.gap != 0 {
368 shape |= SHAPE_HAS_GAP;
369 }
370 if !self.arity.is_fixed() {
371 shape |= SHAPE_VARIABLE_ARITY;
372 }
373 write_leb128(out, shape);
374 if self.gap != 0 {
375 write_leb128(out, self.gap);
376 }
377 if !self.arity.is_fixed() {
378 write_leb128(out, self.arity.extra());
379 }
380 write_leb128(out, self.links.len() as u64);
381 Ok(())
382 }
383
384 fn read_header(reader: &mut dyn Read) -> ProtocolResult<(Self, u64)> {
387 let shape = read_leb128(reader)?;
388 let width = width_from_code(shape & SHAPE_WIDTH_BITS);
389 let gap = if shape & SHAPE_HAS_GAP != 0 {
390 read_leb128(reader)?
391 } else {
392 0
393 };
394 let extra = if shape & SHAPE_VARIABLE_ARITY != 0 {
395 Some(read_leb128(reader)?)
396 } else {
397 None
398 };
399 let arity = ArityRange::from_shape(shape >> SHAPE_MIN_ARITY_SHIFT, extra)?;
400 let count = read_leb128(reader)?;
401 let section = Section {
402 gap,
403 arity,
404 width,
405 links: Vec::new(),
406 };
407 Ok((section, count))
408 }
409
410 fn validate(&self) -> ProtocolResult<()> {
411 width_code(self.width)?;
412 self.arity.validate().map_err(ProtocolError::Unencodable)?;
413 for link in &self.links {
414 if !self.arity.contains(link.len() as u64) {
415 return Err(ProtocolError::Unencodable(format!(
416 "a link of {} references in a section of arity {}",
417 link.len(),
418 self.arity
419 )));
420 }
421 }
422 Ok(())
423 }
424}
425
426impl LinksPacket {
427 pub fn new(external_references: bool) -> Self {
429 Self {
430 external_references,
431 sections: Vec::new(),
432 }
433 }
434
435 pub fn pack(
444 external_references: bool,
445 links: &[(u64, Vec<Reference>)],
446 packed_widths: bool,
447 ) -> ProtocolResult<Self> {
448 let planner = SectionPlanner::new(external_references, links)?;
449 let uniform_layout = planner.plan(false);
450 let uniform = Self::lay_out(external_references, links, &uniform_layout);
451 if !packed_widths {
452 return Ok(uniform);
453 }
454 let packed_layout = planner.plan(true);
455 if packed_layout == uniform_layout {
456 return Ok(uniform);
457 }
458 let packed = Self::lay_out(external_references, links, &packed_layout);
459 Ok(if packed.to_bytes()?.len() < uniform.to_bytes()?.len() {
460 packed
461 } else {
462 uniform
463 })
464 }
465
466 fn lay_out(
468 external_references: bool,
469 links: &[(u64, Vec<Reference>)],
470 layout: &[(usize, u8)],
471 ) -> Self {
472 let mut sections = Vec::with_capacity(layout.len());
473 let mut next_address = 1u64;
474 let mut remaining = links;
475 for &(count, width) in layout {
476 let (members, rest) = remaining.split_at(count);
477 remaining = rest;
478 let start = members[0].0;
479 let (shortest, longest) = members
480 .iter()
481 .map(|(_, link)| link.len() as u64)
482 .fold((u64::MAX, 0), |(shortest, longest), length| {
483 (shortest.min(length), longest.max(length))
484 });
485 sections.push(Section {
486 gap: start - next_address,
487 arity: ArityRange::between(shortest, longest),
488 width,
489 links: members.iter().map(|(_, link)| link.clone()).collect(),
490 });
491 next_address = start + count as u64;
492 }
493 Self {
494 external_references,
495 sections,
496 }
497 }
498
499 pub fn links(&self) -> impl Iterator<Item = (u64, &[Reference])> + '_ {
501 let mut next_address = 1u64;
502 self.sections.iter().flat_map(move |section| {
503 let start = next_address.saturating_add(section.gap);
504 next_address = start.saturating_add(section.links.len() as u64);
505 section
506 .links
507 .iter()
508 .enumerate()
509 .map(move |(index, link)| (start + index as u64, link.as_slice()))
510 })
511 }
512
513 pub fn link_count(&self) -> u64 {
515 self.sections
516 .iter()
517 .map(|section| section.links.len() as u64)
518 .sum()
519 }
520
521 fn is_compact(&self) -> bool {
522 match self.sections.as_slice() {
523 [] => true,
524 [only] => {
525 only.gap == COMPACT_GAP
526 && only.arity == ArityRange::DOUBLETS
527 && !only.links.is_empty()
528 }
529 _ => false,
530 }
531 }
532
533 pub fn to_bytes(&self) -> ProtocolResult<Vec<u8>> {
535 let mut bytes = Vec::new();
536 self.write_to(&mut bytes)?;
537 Ok(bytes)
538 }
539
540 pub fn write_to(&self, writer: &mut dyn Write) -> ProtocolResult<()> {
542 let mut header = BINARY_VERSION_1;
543 if self.external_references {
544 header |= FLAG_EXTERNAL_REFERENCES;
545 }
546 let mut out = Vec::new();
547 let mut next_address = 1u64;
548 for section in &self.sections {
549 section.validate()?;
550 next_address = next_address
551 .checked_add(section.gap)
552 .and_then(|start| start.checked_add(section.links.len() as u64))
553 .ok_or_else(|| ProtocolError::Unencodable("addresses overflow 64 bits".into()))?;
554 }
555 if self.is_compact() {
556 let width = self.sections.first().map_or(1, |section| section.width);
557 header |= width_code(width)? << WIDTH_SHIFT;
558 out.push(header);
559 write_leb128(&mut out, self.link_count());
560 } else {
561 out.push(header | FLAG_EXPLICIT_LAYOUT);
562 write_leb128(&mut out, self.sections.len() as u64);
563 for section in &self.sections {
564 section.write_header(&mut out)?;
565 }
566 }
567 for section in &self.sections {
568 for link in §ion.links {
569 if !section.arity.is_fixed() {
570 write_leb128(&mut out, link.len() as u64 - section.arity.min);
571 }
572 for &reference in link {
573 write_raw(
574 &mut out,
575 self.raw_reference(reference, section.width)?,
576 section.width,
577 );
578 }
579 }
580 }
581 writer.write_all(&out)?;
582 Ok(())
583 }
584
585 fn raw_reference(&self, reference: Reference, width: u8) -> ProtocolResult<u64> {
586 if reference_width(reference, self.external_references)? > width {
587 return Err(ProtocolError::Unencodable(format!(
588 "{reference:?} does not fit {width} byte(s)"
589 )));
590 }
591 Ok(match reference {
592 Reference::Internal(address) => address,
593 Reference::External(value) => encode_external(value, width),
594 })
595 }
596
597 pub fn from_bytes(bytes: &[u8], limits: &DecodeLimits) -> ProtocolResult<Self> {
599 let mut cursor = bytes;
600 let packet = Self::read_from(&mut cursor, limits)?
601 .ok_or_else(|| ProtocolError::malformed("empty input"))?;
602 if !cursor.is_empty() {
603 return Err(ProtocolError::malformed("trailing bytes after the packet"));
604 }
605 Ok(packet)
606 }
607
608 pub fn read_from(reader: &mut dyn Read, limits: &DecodeLimits) -> ProtocolResult<Option<Self>> {
610 let Some(header) = read_byte_or_eof(reader)? else {
611 return Ok(None);
612 };
613 if header & 0xF0 != BINARY_VERSION_1 {
614 return Err(ProtocolError::malformed(format!(
615 "unsupported binary header byte 0x{header:02X}"
616 )));
617 }
618 let mut packet = LinksPacket::new(header & FLAG_EXTERNAL_REFERENCES != 0);
619 let mut counts = Vec::new();
620 if header & FLAG_EXPLICIT_LAYOUT == 0 {
621 let width = width_from_code(u64::from((header & WIDTH_BITS) >> WIDTH_SHIFT));
622 let count = read_leb128(reader)?;
623 if count > 0 {
624 packet.sections.push(Section {
625 gap: COMPACT_GAP,
626 arity: ArityRange::DOUBLETS,
627 width,
628 links: Vec::new(),
629 });
630 counts.push(count);
631 }
632 } else {
633 if header & WIDTH_BITS != 0 {
634 return Err(ProtocolError::malformed(
635 "the explicit layout keeps the header width bits clear",
636 ));
637 }
638 let section_count = read_leb128(reader)?;
639 if section_count > limits.max_links {
640 return Err(Self::too_many_links(limits));
641 }
642 let mut next_address = 1u64;
643 for _ in 0..section_count {
644 let (section, count) = Section::read_header(reader)?;
645 next_address = next_address
646 .checked_add(section.gap)
647 .and_then(|start| start.checked_add(count))
648 .ok_or_else(|| ProtocolError::malformed("addresses overflow 64 bits"))?;
649 packet.sections.push(section);
650 counts.push(count);
651 }
652 }
653 counts
654 .iter()
655 .try_fold(0u64, |total, &count| total.checked_add(count))
656 .filter(|&total| total <= limits.max_links)
657 .ok_or_else(|| Self::too_many_links(limits))?;
658 let mut references_left = limits.max_references;
659 let external_references = packet.external_references;
660 for (section, count) in packet.sections.iter_mut().zip(counts) {
661 section.links.reserve(count.min(4096) as usize);
662 for _ in 0..count {
663 let length = if section.arity.is_fixed() {
664 section.arity.min
665 } else {
666 let length = read_leb128(reader)?
667 .checked_add(section.arity.min)
668 .filter(|&length| section.arity.contains(length))
669 .ok_or_else(|| {
670 ProtocolError::malformed(format!(
671 "link length outside the section arity {}",
672 section.arity
673 ))
674 })?;
675 length
676 };
677 references_left = references_left.checked_sub(length).ok_or_else(|| {
678 ProtocolError::LimitExceeded(format!(
679 "references exceed the limit of {}",
680 limits.max_references
681 ))
682 })?;
683 let mut link = Vec::with_capacity(length.min(4096) as usize);
684 for _ in 0..length {
685 let raw = read_raw(reader, section.width)?;
686 link.push(
687 match decode_external(raw, section.width).filter(|_| external_references) {
688 Some(value) => Reference::External(value),
689 None => Reference::Internal(raw),
690 },
691 );
692 }
693 section.links.push(link);
694 }
695 }
696 Ok(Some(packet))
697 }
698
699 fn too_many_links(limits: &DecodeLimits) -> ProtocolError {
700 ProtocolError::LimitExceeded(format!(
701 "packet declares more than {} links",
702 limits.max_links
703 ))
704 }
705}
706
707const SECTION_HEADER_ESTIMATE: u64 = 2;
709const VARIABLE_ARITY_ESTIMATE: u64 = 1;
712const UNREACHABLE: u64 = u64::MAX / 4;
713const STATES: usize = WIDTHS.len() * 2;
715
716struct SectionPlanner<'a> {
724 links: &'a [(u64, Vec<Reference>)],
725 needs: Vec<u8>,
726}
727
728impl<'a> SectionPlanner<'a> {
729 fn new(external_references: bool, links: &'a [(u64, Vec<Reference>)]) -> ProtocolResult<Self> {
730 let mut needs = Vec::with_capacity(links.len());
731 let mut previous_address = 0u64;
732 for (address, link) in links {
733 if *address <= previous_address {
734 return Err(ProtocolError::Unencodable(format!(
735 "link addresses must ascend from 1, got {address} after {previous_address}"
736 )));
737 }
738 if link.is_empty() {
739 return Err(ProtocolError::Unencodable(format!(
740 "link {address} has no references"
741 )));
742 }
743 previous_address = *address;
744 let mut need = 1u8;
745 for &reference in link {
746 need = need.max(reference_width(reference, external_references)?);
747 }
748 needs.push(need);
749 }
750 Ok(Self { links, needs })
751 }
752
753 fn first_cheapest(costs: &[u64; STATES]) -> usize {
754 let mut best = 0;
755 for state in 1..STATES {
756 if costs[state] < costs[best] {
757 best = state;
758 }
759 }
760 best
761 }
762
763 fn plan(&self, packed_widths: bool) -> Vec<(usize, u8)> {
766 if self.links.is_empty() {
767 return Vec::new();
768 }
769 let widest = self.needs.iter().copied().max().unwrap_or(1);
770 let allowed_widths = WIDTHS.map(|width| packed_widths || width == widest);
771 let mut opens_section = vec![0u8; self.links.len()];
772 let mut previous_best = vec![0u8; self.links.len()];
773 let mut costs = [UNREACHABLE; STATES];
774 for (index, (address, link)) in self.links.iter().enumerate() {
775 let best = Self::first_cheapest(&costs);
776 previous_best[index] = best as u8;
777 let cheapest_before = if index == 0 { 0 } else { costs[best] };
778 let continues = index > 0 && self.links[index - 1].0 + 1 == *address;
779 let same_length = index > 0 && self.links[index - 1].1.len() == link.len();
780 let mut next = [UNREACHABLE; STATES];
781 for state in 0..STATES {
782 let width_index = state / 2;
783 let variable = state % 2 == 1;
784 let width = WIDTHS[width_index];
785 if !allowed_widths[width_index] || width < self.needs[index] {
786 continue;
787 }
788 let variable_estimate = if variable { VARIABLE_ARITY_ESTIMATE } else { 0 };
789 let body = link.len() as u64 * u64::from(width) + variable_estimate;
790 let opening_cost = cheapest_before + SECTION_HEADER_ESTIMATE + variable_estimate;
791 let continuing_cost = if continues && (variable || same_length) {
792 costs[state]
793 } else {
794 UNREACHABLE
795 };
796 if continuing_cost <= opening_cost {
797 next[state] = continuing_cost + body;
798 } else {
799 next[state] = opening_cost + body;
800 opens_section[index] |= 1 << state;
801 }
802 }
803 costs = next;
804 }
805 let mut sections = Vec::new();
806 let mut state = Self::first_cheapest(&costs);
807 let mut end = self.links.len();
808 for index in (0..self.links.len()).rev() {
809 if opens_section[index] & (1 << state) != 0 {
810 sections.push((end - index, WIDTHS[state / 2]));
811 end = index;
812 state = usize::from(previous_best[index]);
813 }
814 }
815 sections.reverse();
816 sections
817 }
818}
819
820fn write_raw(out: &mut Vec<u8>, value: u64, width: u8) {
821 out.extend_from_slice(&value.to_le_bytes()[..usize::from(width)]);
822}
823
824fn read_raw(reader: &mut dyn Read, width: u8) -> ProtocolResult<u64> {
825 let mut bytes = [0u8; 8];
826 read_exact(reader, &mut bytes[..usize::from(width)])?;
827 Ok(u64::from_le_bytes(bytes))
828}
829
830pub fn write_leb128(out: &mut Vec<u8>, mut value: u64) {
832 loop {
833 let byte = (value & 0x7F) as u8;
834 value >>= 7;
835 if value == 0 {
836 out.push(byte);
837 return;
838 }
839 out.push(byte | 0x80);
840 }
841}
842
843pub fn read_leb128(reader: &mut dyn Read) -> ProtocolResult<u64> {
845 let mut value = 0u64;
846 for shift in (0..64).step_by(7) {
847 let mut byte = [0u8; 1];
848 read_exact(reader, &mut byte)?;
849 let payload = u64::from(byte[0] & 0x7F);
850 if shift == 63 && payload > 1 {
851 return Err(ProtocolError::malformed("LEB128 value overflows 64 bits"));
852 }
853 value |= payload << shift;
854 if byte[0] & 0x80 == 0 {
855 return Ok(value);
856 }
857 }
858 Err(ProtocolError::malformed("LEB128 value overflows 64 bits"))
859}
860
861fn read_exact(reader: &mut dyn Read, buffer: &mut [u8]) -> ProtocolResult<()> {
862 reader.read_exact(buffer).map_err(|error| {
863 if error.kind() == io::ErrorKind::UnexpectedEof {
864 ProtocolError::malformed("unexpected end of packet")
865 } else {
866 ProtocolError::Io(error)
867 }
868 })
869}
870
871fn read_byte_or_eof(reader: &mut dyn Read) -> ProtocolResult<Option<u8>> {
873 let mut byte = [0u8; 1];
874 loop {
875 match reader.read(&mut byte) {
876 Ok(0) => return Ok(None),
877 Ok(_) => return Ok(Some(byte[0])),
878 Err(error) if error.kind() == io::ErrorKind::Interrupted => {}
879 Err(error) => return Err(error.into()),
880 }
881 }
882}