1
#![forbid(unsafe_code)]
2

            
3
use std::collections::VecDeque;
4
use std::io::Error;
5
use std::io::ErrorKind;
6
use std::io::Read;
7
use std::io::Write;
8

            
9
use merc_collections::IndexedSet;
10
use merc_io::BitStreamRead;
11
use merc_io::BitStreamReader;
12
use merc_io::BitStreamWrite;
13
use merc_io::BitStreamWriter;
14
use merc_number::bits_for_value;
15
use merc_utilities::MercError;
16
use merc_utilities::debug_trace;
17

            
18
use crate::ATerm;
19
use crate::ATermInt;
20
use crate::ATermIntRef;
21
use crate::ATermRef;
22
use crate::Protected;
23
use crate::Symb;
24
use crate::Symbol;
25
use crate::SymbolRef;
26
use crate::Term;
27
use crate::is_int_symbol;
28
use crate::is_int_term;
29

            
30
/// The magic value for a binary aterm format stream.
31
/// As of version 0x8305 the magic and version are written as 2 bytes not encoded as variable-width integers.
32
/// To ensure compatibility with older formats the previously variable-width encoding is mimicked by prefixing them with 1000 (0x8).
33
const BAF_MAGIC: u16 = 0x8baf;
34

            
35
/// The BAF_VERSION constant is the version number of the ATerms written in BAF format.
36
/// History:
37
/// - before 2013: version 0x0300
38
/// - 29 August 2013: version changed to 0x0301
39
/// - 23 November 2013: version changed to 0x0302 (introduction of index for variable types)
40
/// - 24 September 2014: version changed to 0x0303 (introduction of stochastic distribution)
41
/// - 2 April 2017: version changed to 0x0304 (removed a few superfluous fields in the format)
42
/// - 19 July 2019: version changed to 0x8305 (introduction of the streamable aterm format)
43
/// - 28 February 2020: version changed to 0x8306 (added ability to stream aterm_int,
44
///   implemented structured streaming for all objects)
45
/// - 24 January 2023: version changed to 0x8307 (removed NoIndex from Variables, Boolean variables.
46
///   Made the .lts format more compact by not storing states with a default probability 1)
47
/// - 6 August 2024: version changed to 0x8308 (introduced machine numbers)
48
const BAF_VERSION: u16 = 0x8308;
49

            
50
/// Each packet has a header consisting of a type.
51
/// Either indicates a function symbol, a term (either shared or output) or an arbitrary integer.
52
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53
#[repr(u8)]
54
enum PacketType {
55
    FunctionSymbol = 0,
56
    ATerm = 1,
57
    ATermOutput = 2,
58
    ATermIntOutput = 3,
59
}
60

            
61
/// The number of bits needed to store an element of PacketType.
62
const PACKET_BITS: u8 = 2;
63

            
64
impl From<u8> for PacketType {
65
3772180
    fn from(value: u8) -> Self {
66
3772180
        match value {
67
17860
            0 => PacketType::FunctionSymbol,
68
32430
            1 => PacketType::ATerm,
69
1867830
            2 => PacketType::ATermOutput,
70
1854060
            3 => PacketType::ATermIntOutput,
71
            _ => panic!("Invalid packet type: {value}"),
72
        }
73
3772180
    }
74
}
75

            
76
/// Trait for writing ATerms to a stream.
77
pub trait ATermWrite {
78
    /// Writes an ATerm to the stream.
79
    fn write_aterm(&mut self, term: &ATerm) -> Result<(), MercError>;
80

            
81
    /// Writes an iterator of ATerms to the stream.
82
    fn write_aterm_iter<I>(&mut self, iter: I) -> Result<(), MercError>
83
    where
84
        I: ExactSizeIterator<Item = ATerm>;
85

            
86
    /// Flushes any remaining data and writes the end-of-stream marker.
87
    ///
88
    /// This method should be called when you're done writing terms to ensure
89
    /// all data is properly written and the stream is correctly terminated.
90
    fn flush(&mut self) -> Result<(), MercError>;
91
}
92

            
93
/// Trait for reading ATerms from a stream.
94
pub trait ATermRead {
95
    /// Reads the next ATerm from the stream. Returns None when the end of the stream is reached.
96
    fn read_aterm(&mut self) -> Result<Option<ATerm>, MercError>;
97

            
98
    /// Reads an iterator of ATerms from the stream.
99
    fn read_aterm_iter(&mut self) -> Result<impl ExactSizeIterator<Item = Result<ATerm, MercError>>, MercError>;
100
}
101

            
102
/// Trait for objects that can be written to and read from an ATerm stream.
103
pub trait ATermStreamable {
104
    /// Writes the object to the given ATerm writer.
105
    fn write<W: ATermWrite>(&self, writer: &mut W) -> Result<(), MercError>;
106

            
107
    /// Reads the object from the given ATerm reader.
108
    fn read<R: ATermRead>(reader: &mut R) -> Result<Self, MercError>
109
    where
110
        Self: Sized;
111
}
112

            
113
/// Writes terms in a streamable binary aterm format to an output stream.
114
///
115
/// # The streamable aterm format:
116
///
117
/// Aterms (and function symbols) are written as packets (with an identifier in
118
/// the header) and their indices are derived from the number of aterms, resp.
119
/// symbols, that occur before them in this stream. For each term we first
120
/// ensure that its arguments and symbol are written to the stream (avoiding
121
/// duplicates). Then its symbol index followed by a number of indices
122
/// (depending on the arity) for its argments are written as integers. Packet
123
/// headers also contain a special value to indicate that the read term should
124
/// be visible as output as opposed to being only a subterm. The start of the
125
/// stream is a zero followed by a header and a version and a term with function
126
/// symbol index zero indicates the end of the stream.
127
///
128
pub struct BinaryATermWriter<W: Write> {
129
    stream: BitStreamWriter<W>,
130

            
131
    /// Stores the function symbols and the number of bits needed to encode their indices.
132
    function_symbols: IndexedSet<Symbol>,
133
    function_symbol_index_width: u8,
134

            
135
    /// Stores the terms and the number of bits needed to encode their indices.
136
    terms: IndexedSet<ATerm>,
137
    term_index_width: u8,
138

            
139
    /// Indicates whether the stream has been flushed.
140
    flushed: bool,
141

            
142
    /// Local stack to avoid recursive function calls when writing terms.
143
    stack: VecDeque<(ATerm, bool)>,
144
}
145

            
146
impl<W: Write> BinaryATermWriter<W> {
147
    /// Creates a new binary ATerm output stream with the given writer.
148
    ///
149
    /// # Arguments
150
    /// * `writer` - The underlying writer to write binary data to
151
    ///
152
    /// # Returns
153
    /// A new `BinaryATermOutputStream` instance or an error if header writing fails
154
300
    pub fn new(writer: W) -> Result<Self, MercError> {
155
300
        let mut stream = BitStreamWriter::new(writer);
156

            
157
        // Write the header of the binary aterm format
158
300
        stream.write_bits(0, 8)?;
159
300
        stream.write_bits(BAF_MAGIC as u64, 16)?;
160
300
        stream.write_bits(BAF_VERSION as u64, 16)?;
161

            
162
300
        let mut function_symbols = IndexedSet::new();
163
        // The term with function symbol index 0 indicates the end of the stream
164
300
        function_symbols.insert(Symbol::new("end_of_stream".to_string(), 0));
165

            
166
300
        Ok(Self {
167
300
            stream,
168
300
            function_symbols,
169
300
            function_symbol_index_width: 1,
170
300
            terms: IndexedSet::new(),
171
300
            term_index_width: 1,
172
300
            stack: VecDeque::new(),
173
300
            flushed: false,
174
300
        })
175
300
    }
176

            
177
    /// \brief Write a function symbol to the output stream.
178
190590
    fn write_function_symbol(&mut self, symbol: &SymbolRef<'_>) -> Result<usize, MercError> {
179
190590
        let (index, inserted) = self.function_symbols.insert(symbol.protect());
180

            
181
190590
        if inserted {
182
            // Write the function symbol to the stream
183
2200
            self.stream.write_bits(PacketType::FunctionSymbol as u64, PACKET_BITS)?;
184
2200
            self.stream.write_string(symbol.name())?;
185
2200
            self.stream.write_integer(symbol.arity() as u64)?;
186
2200
            self.function_symbol_index_width = bits_for_value(self.function_symbols.len());
187
188390
        }
188

            
189
190590
        Ok(*index)
190
190590
    }
191

            
192
    /// Returns the current bit width needed to encode a function symbol index.
193
    ///
194
    /// In debug builds, this asserts that the cached width equals the
195
    /// computed width based on the current number of function symbols.
196
190890
    fn function_symbol_index_width(&self) -> u8 {
197
190890
        let expected = bits_for_value(self.function_symbols.len());
198
190890
        debug_assert_eq!(
199
            self.function_symbol_index_width, expected,
200
            "function_symbol_index_width does not match bits_for_value",
201
        );
202

            
203
190890
        self.function_symbol_index_width
204
190890
    }
205

            
206
    /// Returns the current bit width needed to encode a term index.
207
    ///
208
    /// In debug builds, this asserts that the cached width equals the
209
    /// computed width based on the current number of terms.
210
192011
    fn term_index_width(&self) -> u8 {
211
192011
        let expected = bits_for_value(self.terms.len());
212
192011
        debug_assert_eq!(
213
            self.term_index_width, expected,
214
            "term_index_width does not match bits_for_value",
215
        );
216
192011
        self.term_index_width
217
192011
    }
218
}
219

            
220
impl<W: Write> ATermWrite for BinaryATermWriter<W> {
221
374180
    fn write_aterm(&mut self, term: &ATerm) -> Result<(), MercError> {
222
374180
        self.stack.push_back((term.clone(), false));
223

            
224
1126035
        while let Some((current_term, write_ready)) = self.stack.pop_back() {
225
            // Indicates that this term is output and not a subterm, these should always be written.
226
751855
            let is_output = self.stack.is_empty();
227

            
228
751855
            if !self.terms.contains(&current_term) || is_output {
229
751760
                if write_ready {
230
375880
                    if is_int_term(&current_term) {
231
185290
                        let int_term = ATermIntRef::from(current_term.copy());
232
185290
                        if is_output {
233
                            // If the integer is output, write the header and just an integer
234
185290
                            self.stream.write_bits(PacketType::ATermIntOutput as u64, PACKET_BITS)?;
235
185290
                            self.stream.write_integer(int_term.value() as u64)?;
236
                        } else {
237
                            let symbol_index = self.write_function_symbol(&int_term.get_head_symbol())?;
238

            
239
                            self.stream.write_bits(PacketType::ATerm as u64, PACKET_BITS)?;
240
                            self.stream
241
                                .write_bits(symbol_index as u64, self.function_symbol_index_width())?;
242
                            self.stream.write_integer(int_term.value() as u64)?;
243
                        }
244
                    } else {
245
190590
                        let symbol_index = self.write_function_symbol(&current_term.get_head_symbol())?;
246
190590
                        let packet_type = if is_output {
247
188890
                            PacketType::ATermOutput
248
                        } else {
249
1700
                            PacketType::ATerm
250
                        };
251

            
252
190590
                        self.stream.write_bits(packet_type as u64, PACKET_BITS)?;
253
190590
                        self.stream
254
190590
                            .write_bits(symbol_index as u64, self.function_symbol_index_width())?;
255

            
256
192211
                        for arg in current_term.arguments() {
257
192011
                            let index = self.terms.index(&arg).expect("Argument must already be written");
258
192011
                            self.stream.write_bits(*index as u64, self.term_index_width())?;
259
                        }
260
                    }
261

            
262
375880
                    if !is_output {
263
1700
                        let (_, inserted) = self.terms.insert(current_term);
264
1700
                        assert!(inserted, "This term should have a new index assigned.");
265
1700
                        self.term_index_width = bits_for_value(self.terms.len());
266
374180
                    }
267
                } else {
268
                    // Add current term back to stack for writing after processing arguments
269
375880
                    self.stack.push_back((current_term.clone(), true));
270

            
271
                    // Add arguments to stack for processing first
272
377401
                    for arg in current_term.arguments() {
273
192011
                        if !self.terms.contains(&arg) {
274
1795
                            self.stack.push_back((arg.protect(), false));
275
190216
                        }
276
                    }
277
                }
278
95
            }
279

            
280
            // This term was already written and as such should be skipped. This can happen if
281
            // one term has two equal subterms.
282
        }
283

            
284
374180
        Ok(())
285
374180
    }
286

            
287
600
    fn write_aterm_iter<I>(&mut self, iter: I) -> Result<(), MercError>
288
600
    where
289
600
        I: ExactSizeIterator<Item = ATerm>,
290
    {
291
600
        self.write_aterm(&ATermInt::new(iter.len()))?;
292
2500
        for ldd in iter {
293
2000
            self.write_aterm(&ldd)?;
294
        }
295
600
        Ok(())
296
600
    }
297

            
298
300
    fn flush(&mut self) -> Result<(), MercError> {
299
        // Write the end of stream marker
300
300
        self.stream.write_bits(PacketType::ATerm as u64, PACKET_BITS)?;
301
300
        self.stream.write_bits(0, self.function_symbol_index_width())?;
302
300
        self.stream.flush()?;
303
300
        self.flushed = true;
304
300
        Ok(())
305
300
    }
306
}
307

            
308
impl<W: Write> BitStreamWrite for BinaryATermWriter<W> {
309
    delegate::delegate! {
310
        to self.stream {
311
            fn write_bits(&mut self, value: u64, number_of_bits: u8) -> Result<(), MercError>;
312
            fn write_string(&mut self, s: &str) -> Result<(), MercError>;
313
            fn write_integer(&mut self, value: u64) -> Result<(), MercError>;
314
            fn flush(&mut self) -> Result<(), MercError>;
315
        }
316
    }
317
}
318

            
319
impl<W: Write> Drop for BinaryATermWriter<W> {
320
300
    fn drop(&mut self) {
321
300
        if !self.flushed {
322
100
            ATermWrite::flush(self).expect("Panicked while flushing the stream when dropped");
323
300
        }
324
300
    }
325
}
326

            
327
/// The reader counterpart of [`BinaryATermWriter`], which reads ATerms from a binary aterm input stream.
328
pub struct BinaryATermReader<R: Read> {
329
    stream: BitStreamReader<R>,
330

            
331
    /// Stores the function symbols read so far, and the width needed to encode their indices.
332
    function_symbols: Protected<Vec<SymbolRef<'static>>>,
333
    function_symbol_index_width: u8,
334

            
335
    /// Stores the terms read so far, and the width needed to encode their indices.
336
    terms: Protected<Vec<ATermRef<'static>>>,
337
    term_index_width: u8,
338

            
339
    /// Indicates whether the end of stream marker has already been encountered.
340
    ended: bool,
341
}
342

            
343
impl<R: Read> BinaryATermReader<R> {
344
    /// Checks for the header and initializes the binary aterm input stream.
345
304
    pub fn new(reader: R) -> Result<Self, MercError> {
346
304
        let mut stream = BitStreamReader::new(reader);
347

            
348
        // Read the binary aterm format header
349
304
        if stream.read_bits(8)? != 0 || stream.read_bits(16)? != BAF_MAGIC as u64 {
350
            return Err(Error::new(ErrorKind::InvalidData, "Missing BAF_MAGIC control sequence").into());
351
304
        }
352

            
353
304
        let version = stream.read_bits(16)?;
354
304
        if version != BAF_VERSION as u64 {
355
            return Err(Error::new(
356
                ErrorKind::InvalidData,
357
                format!("BAF version ({version}) incompatible with expected version ({BAF_VERSION})"),
358
            )
359
            .into());
360
304
        }
361

            
362
        // The term with function symbol index 0 indicates the end of the stream
363
304
        let mut function_symbols = Protected::new(Vec::new());
364
304
        let end_of_stream_symbol = Symbol::new(String::new(), 0);
365
304
        function_symbols.write().push(end_of_stream_symbol.copy());
366

            
367
304
        Ok(Self {
368
304
            stream,
369
304
            function_symbols,
370
304
            function_symbol_index_width: 1,
371
304
            terms: Protected::new(Vec::new()),
372
304
            term_index_width: 1,
373
304
            ended: false,
374
304
        })
375
304
    }
376

            
377
    /// Returns the current bit width needed to encode a function symbol index.
378
    ///
379
    /// In debug builds, this asserts that the cached width equals the
380
    /// computed width based on the current number of function symbols.
381
193986
    fn function_symbol_index_width(&self) -> u8 {
382
193986
        let expected = bits_for_value(self.function_symbols.read().len());
383
193986
        debug_assert_eq!(
384
            self.function_symbol_index_width, expected,
385
            "function_symbol_index_width does not match bits_for_value",
386
        );
387

            
388
193986
        self.function_symbol_index_width
389
193986
    }
390

            
391
    /// Returns a mutable reference to the underlying bit stream reader.
392
    pub fn stream(&mut self) -> &mut BitStreamReader<R> {
393
        &mut self.stream
394
    }
395

            
396
    /// Returns the current bit width needed to encode a term index.
397
    ///
398
    /// In debug builds, this asserts that the cached width equals the
399
    /// computed width based on the current number of terms.
400
99963
    fn term_index_width(&self) -> u8 {
401
99963
        let expected = bits_for_value(self.terms.read().len());
402
99963
        debug_assert_eq!(
403
            self.term_index_width, expected,
404
            "term_index_width does not match bits_for_value",
405
        );
406
99963
        self.term_index_width
407
99963
    }
408
}
409

            
410
impl<R: Read> ATermRead for BinaryATermReader<R> {
411
375980
    fn read_aterm(&mut self) -> Result<Option<ATerm>, MercError> {
412
375980
        if self.ended {
413
            return Err(Error::new(
414
                ErrorKind::UnexpectedEof,
415
                "Attempted to read_aterm() after end of stream",
416
            )
417
            .into());
418
375980
        }
419

            
420
        loop {
421
381988
            let header = self.stream.read_bits(PACKET_BITS)?;
422
381988
            let packet = PacketType::from(header as u8);
423
381988
            debug_trace!("Read packet: {:?}", packet);
424

            
425
381988
            match packet {
426
                PacketType::FunctionSymbol => {
427
2506
                    let name = self.stream.read_string()?;
428
2506
                    let arity = self.stream.read_integer()? as usize;
429
2506
                    let symbol = Symbol::new(name, arity);
430
2506
                    debug_trace!("Read symbol {symbol}");
431

            
432
2506
                    let mut write_symbols = self.function_symbols.write();
433
2506
                    let s = write_symbols.protect_symbol(&symbol);
434
2506
                    write_symbols.push(s);
435
2506
                    self.function_symbol_index_width = bits_for_value(write_symbols.len());
436
                }
437
                PacketType::ATermIntOutput => {
438
185496
                    let value = self.stream.read_integer()?.try_into()?;
439
185496
                    debug_trace!("Output int term: {}", ATermInt::new(value));
440
185496
                    return Ok(Some(ATermInt::new(value).into()));
441
                }
442
                PacketType::ATerm | PacketType::ATermOutput => {
443
193986
                    let symbol_index = self.stream.read_bits(self.function_symbol_index_width())? as usize;
444
193986
                    if symbol_index == 0 {
445
                        // End of stream marker
446
101
                        debug_trace!("End of stream marker reached");
447
101
                        self.ended = true;
448
101
                        return Ok(None);
449
193885
                    }
450

            
451
193885
                    let symbols = self.function_symbols.read();
452
193885
                    let symbol = symbols.get(symbol_index).ok_or(format!(
453
                        "Read invalid function symbol index {symbol_index}, length {}",
454
193885
                        symbols.len()
455
                    ))?;
456

            
457
193885
                    if is_int_symbol(symbol) {
458
26
                        let value = self.stream.read_integer()?.try_into()?;
459
26
                        let term = ATermInt::new(value);
460
26
                        debug_trace!("Read int term: {term}");
461

            
462
26
                        let mut write_terms = self.terms.write();
463
26
                        let t = write_terms.protect(&term);
464
26
                        write_terms.push(t);
465
26
                        self.term_index_width = bits_for_value(write_terms.len());
466
                    } else {
467
                        // When the arity is zero, no bits are read for the arguments.
468
193859
                        let num_of_bits = if symbol.arity() > 0 { self.term_index_width() } else { 0 };
469
193859
                        let mut write_terms = self.terms.write();
470
198165
                        for _ in 0..symbol.arity() {}
471

            
472
193859
                        let term = ATerm::try_with_iter(
473
193859
                            symbol,
474
198165
                            (0..symbol.arity()).map(|_| {
475
198165
                                let arg_index = self.stream.read_bits(num_of_bits)? as usize;
476
198165
                                let arg = write_terms.get(arg_index).ok_or(format!(
477
                                    "Read invalid aterm index {arg_index}, length {}",
478
198165
                                    write_terms.len()
479
                                ))?;
480
198165
                                debug_trace!("Read arg: {arg}");
481
198165
                                Ok(arg)
482
198165
                            }),
483
                        )?;
484

            
485
193859
                        if packet == PacketType::ATermOutput {
486
190383
                            debug_trace!("Output term: {term}");
487
190383
                            return Ok(Some(term));
488
3476
                        }
489
3476
                        debug_trace!("Read term: {term}");
490

            
491
3476
                        let t = write_terms.protect(&term);
492
3476
                        write_terms.push(t);
493
3476
                        self.term_index_width = bits_for_value(write_terms.len());
494
                    }
495
                }
496
            }
497
        }
498
375980
    }
499

            
500
620
    fn read_aterm_iter(&mut self) -> Result<impl ExactSizeIterator<Item = Result<ATerm, MercError>>, MercError> {
501
620
        if self.ended {
502
            return Err(Error::new(
503
                ErrorKind::UnexpectedEof,
504
                "Attempted to read_aterm_iter() after end of stream",
505
            )
506
            .into());
507
620
        }
508

            
509
620
        let number_of_elements: ATermInt = self
510
620
            .read_aterm()?
511
620
            .ok_or("Missing number of elements for iterator")?
512
620
            .into();
513
620
        Ok(ATermReadIter {
514
620
            reader: self,
515
620
            remaining: number_of_elements.value(),
516
620
        })
517
620
    }
518
}
519

            
520
impl<R: Read> BitStreamRead for BinaryATermReader<R> {
521
    delegate::delegate! {
522
        to self.stream {
523
30872
            fn read_bits(&mut self, number_of_bits: u8) -> Result<u64, MercError>;
524
            fn read_string(&mut self) -> Result<String, MercError>;
525
10504
            fn read_integer(&mut self) -> Result<u64, MercError>;
526
        }
527
    }
528
}
529

            
530
/// A read iterator for ATerms from a binary aterm input stream.
531
pub struct ATermReadIter<'a, R: Read> {
532
    reader: &'a mut BinaryATermReader<R>,
533
    remaining: usize,
534
}
535

            
536
impl<'a, R: Read> Iterator for ATermReadIter<'a, R> {
537
    type Item = Result<ATerm, MercError>;
538

            
539
2522
    fn next(&mut self) -> Option<Self::Item> {
540
2522
        if self.remaining == 0 {
541
520
            return None;
542
2002
        }
543

            
544
2002
        self.remaining -= 1;
545
2002
        match self.reader.read_aterm() {
546
2002
            Ok(Some(term)) => Some(Ok(term)),
547
            Ok(None) => Some(Err(Error::new(
548
                ErrorKind::UnexpectedEof,
549
                "Unexpected end of stream while reading iterator",
550
            )
551
            .into())),
552
            Err(e) => Some(Err(e)),
553
        }
554
2522
    }
555

            
556
1
    fn size_hint(&self) -> (usize, Option<usize>) {
557
1
        (self.remaining, Some(self.remaining))
558
1
    }
559
}
560

            
561
impl<'a, R: Read> ExactSizeIterator for ATermReadIter<'a, R> {
562
    fn len(&self) -> usize {
563
        self.remaining
564
    }
565
}
566

            
567
#[cfg(test)]
568
mod tests {
569
    use merc_utilities::random_test;
570

            
571
    use crate::random_term;
572

            
573
    use super::*;
574

            
575
    #[test]
576
    #[cfg_attr(miri, ignore)] // Miri is too slow
577
1
    fn test_random_binary_stream() {
578
100
        random_test(100, |rng| {
579
100
            let input: Vec<_> = (0..20)
580
2000
                .map(|_| random_term(rng, &[("f".into(), 2), ("g".into(), 1)], &["a".into(), "b".into()], 1))
581
100
                .collect();
582

            
583
100
            let mut stream: Vec<u8> = Vec::new();
584

            
585
100
            let mut output_stream = BinaryATermWriter::new(&mut stream).unwrap();
586
2000
            for term in &input {
587
2000
                output_stream.write_aterm(term).unwrap();
588
2000
            }
589
100
            ATermWrite::flush(&mut output_stream).expect("Flushing the output to the stream");
590
100
            drop(output_stream); // Explicitly drop to release the mutable borrow
591

            
592
100
            let mut input_stream = BinaryATermReader::new(&stream[..]).unwrap();
593
2000
            for term in &input {
594
2000
                println!("Term {}", term);
595
2000
                debug_assert_eq!(
596
                    *term,
597
2000
                    input_stream.read_aterm().unwrap().unwrap(),
598
                    "The read term must match the term that we have written"
599
                );
600
            }
601
100
        });
602
1
    }
603

            
604
    #[test]
605
    #[cfg_attr(miri, ignore)] // Miri is too slow
606
1
    fn test_random_binary_stream_iter() {
607
100
        random_test(100, |rng| {
608
100
            let input: Vec<_> = (0..20)
609
2000
                .map(|_| random_term(rng, &[("f".into(), 2), ("g".into(), 1)], &["a".into(), "b".into()], 1))
610
100
                .collect();
611

            
612
100
            let mut stream: Vec<u8> = Vec::new();
613

            
614
100
            let mut output_stream = BinaryATermWriter::new(&mut stream).unwrap();
615
100
            output_stream.write_aterm_iter(input.iter().cloned()).unwrap();
616
100
            ATermWrite::flush(&mut output_stream).expect("Flushing the output to the stream");
617
100
            drop(output_stream); // Explicitly drop to release the mutable borrow
618

            
619
100
            let mut input_stream = BinaryATermReader::new(&stream[..]).unwrap();
620
100
            let read_iter = input_stream.read_aterm_iter().unwrap();
621
2000
            for (term_written, term_read) in input.iter().zip(read_iter) {
622
2000
                let term_read = term_read.expect("Reading term from stream must succeed");
623
2000
                println!("Term {}", term_written);
624
2000
                debug_assert_eq!(
625
                    *term_written, term_read,
626
                    "The read term must match the term that we have written"
627
                );
628
            }
629
100
        });
630
1
    }
631
}