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
use crate::storage::THREAD_TERM_POOL;
30

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

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

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

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

            
65
impl From<u8> for PacketType {
66
6549652
    fn from(value: u8) -> Self {
67
6549652
        match value {
68
29472
            0 => PacketType::FunctionSymbol,
69
55872
            1 => PacketType::ATerm,
70
3243760
            2 => PacketType::ATermOutput,
71
3220548
            3 => PacketType::ATermIntOutput,
72
            _ => panic!("Invalid packet type: {value}"),
73
        }
74
6549652
    }
75
}
76

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

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

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

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

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

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

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

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

            
132
    /// Stores the function symbols and the number of bits needed to encode their indices.
133
    function_symbols: Protected<IndexedSet<SymbolRef<'static>>>,
134
    function_symbol_index_width: u8,
135

            
136
    /// Stores the terms and the number of bits needed to encode their indices.
137
    terms: Protected<IndexedSet<ATermRef<'static>>>,
138
    term_index_width: u8,
139

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

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

            
147
impl<W: Write> BinaryATermWriter<W> {
148
    /// Creates a new binary ATerm output stream with the given writer.
149
300
    pub fn new(writer: W) -> Result<Self, MercError> {
150
300
        let mut stream = BitStreamWriter::new(writer);
151

            
152
        // Write the header of the binary aterm format
153
300
        stream.write_bits(0, 8)?;
154
300
        stream.write_bits(BAF_MAGIC as u64, 16)?;
155
300
        stream.write_bits(BAF_VERSION as u64, 16)?;
156

            
157
300
        let mut function_symbols = Protected::new(IndexedSet::new());
158
        // The term with function symbol index 0 indicates the end of the stream
159
300
        let end_of_stream_symbol = Symbol::new("end_of_stream".to_string(), 0);
160
300
        function_symbols.write().insert(end_of_stream_symbol.copy());
161

            
162
300
        Ok(Self {
163
300
            stream,
164
300
            function_symbols,
165
300
            function_symbol_index_width: 1,
166
300
            terms: Protected::new(IndexedSet::new()),
167
300
            term_index_width: 1,
168
300
            stack: VecDeque::new(),
169
300
            flushed: false,
170
300
        })
171
300
    }
172

            
173
    /// \brief Write a function symbol to the output stream.
174
206462
    fn write_function_symbol(&mut self, symbol: &SymbolRef<'_>) -> Result<usize, MercError> {
175
206462
        let (index, inserted) = self.function_symbols.write().insert(symbol.copy());
176

            
177
206462
        if inserted {
178
            // Write the function symbol to the stream
179
2200
            self.stream.write_bits(PacketType::FunctionSymbol as u64, PACKET_BITS)?;
180
2200
            self.stream.write_string(symbol.name())?;
181
2200
            self.stream.write_integer(symbol.arity() as u64)?;
182
2200
            self.function_symbol_index_width = bits_for_value(self.function_symbols.read().len());
183
204262
        }
184

            
185
206462
        Ok(*index)
186
206462
    }
187

            
188
    /// Returns the current bit width needed to encode a function symbol index.
189
206762
    fn function_symbol_index_width(&self) -> u8 {
190
206762
        let expected = bits_for_value(self.function_symbols.read().len());
191
206762
        debug_assert_eq!(
192
            self.function_symbol_index_width, expected,
193
            "function_symbol_index_width does not match bits_for_value",
194
        );
195

            
196
206762
        self.function_symbol_index_width
197
206762
    }
198

            
199
    /// Returns the current bit width needed to encode a term index.
200
207902
    fn term_index_width(&self) -> u8 {
201
207902
        let expected = bits_for_value(self.terms.read().len());
202
207902
        debug_assert_eq!(
203
            self.term_index_width, expected,
204
            "term_index_width does not match bits_for_value",
205
        );
206
207902
        self.term_index_width
207
207902
    }
208
}
209

            
210
impl<W: Write> ATermWrite for BinaryATermWriter<W> {
211
405924
    fn write_aterm(&mut self, term: &ATerm) -> Result<(), MercError> {
212
405924
        self.stack.push_back((term.clone(), false));
213

            
214
1221259
        while let Some((current_term, write_ready)) = self.stack.pop_back() {
215
            // Indicates that this term is output and not a subterm, these should always be written.
216
815335
            let is_output = self.stack.is_empty();
217

            
218
815335
            if !self.terms.read().contains(&current_term.copy()) || is_output {
219
815248
                if write_ready {
220
407624
                    if is_int_term(&current_term) {
221
201162
                        let int_term = ATermIntRef::from(current_term.copy());
222
201162
                        if is_output {
223
                            // If the integer is output, write the header and just an integer
224
201162
                            self.stream.write_bits(PacketType::ATermIntOutput as u64, PACKET_BITS)?;
225
201162
                            self.stream.write_integer(int_term.value() as u64)?;
226
                        } else {
227
                            let symbol_index = self.write_function_symbol(&int_term.get_head_symbol())?;
228

            
229
                            self.stream.write_bits(PacketType::ATerm as u64, PACKET_BITS)?;
230
                            self.stream
231
                                .write_bits(symbol_index as u64, self.function_symbol_index_width())?;
232
                            self.stream.write_integer(int_term.value() as u64)?;
233
                        }
234
                    } else {
235
206462
                        let symbol_index = self.write_function_symbol(&current_term.get_head_symbol())?;
236
206462
                        let packet_type = if is_output {
237
204762
                            PacketType::ATermOutput
238
                        } else {
239
1700
                            PacketType::ATerm
240
                        };
241

            
242
206462
                        self.stream.write_bits(packet_type as u64, PACKET_BITS)?;
243
206462
                        self.stream
244
206462
                            .write_bits(symbol_index as u64, self.function_symbol_index_width())?;
245

            
246
208102
                        for arg in current_term.arguments() {
247
207902
                            let index = self.terms.read().index(&arg).expect("Argument must already be written");
248
207902
                            self.stream.write_bits(*index as u64, self.term_index_width())?;
249
                        }
250
                    }
251

            
252
407624
                    if !is_output {
253
1700
                        let (_, inserted) = self.terms.write().insert(current_term.copy());
254
1700
                        assert!(inserted, "This term should have a new index assigned.");
255
1700
                        self.term_index_width = bits_for_value(self.terms.read().len());
256
405924
                    }
257
                } else {
258
                    // Add current term back to stack for writing after processing arguments
259
407624
                    self.stack.push_back((current_term.clone(), true));
260

            
261
                    // Add arguments to stack for processing first
262
409164
                    for arg in current_term.arguments() {
263
207902
                        if !self.terms.read().contains(&arg) {
264
1787
                            self.stack.push_back((arg.protect(), false));
265
206115
                        }
266
                    }
267
                }
268
87
            }
269

            
270
            // This term was already written and as such should be skipped. This can happen if
271
            // one term has two equal subterms.
272
        }
273

            
274
405924
        Ok(())
275
405924
    }
276

            
277
600
    fn write_aterm_iter<I>(&mut self, iter: I) -> Result<(), MercError>
278
600
    where
279
600
        I: ExactSizeIterator<Item = ATerm>,
280
    {
281
600
        self.write_aterm(&ATermInt::new(iter.len()))?;
282
2500
        for ldd in iter {
283
2000
            self.write_aterm(&ldd)?;
284
        }
285
600
        Ok(())
286
600
    }
287

            
288
300
    fn flush(&mut self) -> Result<(), MercError> {
289
        // Write the end of stream marker
290
300
        self.stream.write_bits(PacketType::ATerm as u64, PACKET_BITS)?;
291
300
        self.stream.write_bits(0, self.function_symbol_index_width())?;
292
300
        self.stream.flush()?;
293
300
        self.flushed = true;
294
300
        Ok(())
295
300
    }
296
}
297

            
298
impl<W: Write> BitStreamWrite for BinaryATermWriter<W> {
299
    delegate::delegate! {
300
        to self.stream {
301
            fn write_bits(&mut self, value: u64, number_of_bits: u8) -> Result<(), MercError>;
302
            fn write_string(&mut self, s: &str) -> Result<(), MercError>;
303
            fn write_integer(&mut self, value: u64) -> Result<(), MercError>;
304
            fn flush(&mut self) -> Result<(), MercError>;
305
        }
306
    }
307
}
308

            
309
impl<W: Write> Drop for BinaryATermWriter<W> {
310
300
    fn drop(&mut self) {
311
300
        if !self.flushed {
312
100
            ATermWrite::flush(self).expect("Panicked while flushing the stream when dropped");
313
300
        }
314

            
315
300
        self.function_symbols.write().clear();
316
300
        self.terms.write().clear();
317

            
318
        // Perform garbage collection after clearing the terms, since they might become unreachable.
319
300
        THREAD_TERM_POOL.with_borrow(|tp| tp.collect_garbage());
320
300
    }
321
}
322

            
323
/// The reader counterpart of [BinaryATermWriter], which reads ATerms from a binary aterm input stream.
324
pub struct BinaryATermReader<R: Read> {
325
    stream: BitStreamReader<R>,
326

            
327
    /// Stores the function symbols read so far, and the width needed to encode their indices.
328
    function_symbols: Protected<Vec<SymbolRef<'static>>>,
329
    function_symbol_index_width: u8,
330

            
331
    /// Stores the terms read so far, and the width needed to encode their indices.
332
    terms: Protected<Vec<ATermRef<'static>>>,
333
    term_index_width: u8,
334

            
335
    /// Indicates whether the end of stream marker has already been encountered.
336
    ended: bool,
337
}
338

            
339
impl<R: Read> BinaryATermReader<R> {
340
    /// Checks for the header and initializes the binary aterm input stream.
341
306
    pub fn new(reader: R) -> Result<Self, MercError> {
342
306
        let mut stream = BitStreamReader::new(reader);
343

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

            
349
306
        let version = stream.read_bits(16)?;
350
306
        if version != BAF_VERSION as u64 {
351
            return Err(Error::new(
352
                ErrorKind::InvalidData,
353
                format!("BAF version ({version}) incompatible with expected version ({BAF_VERSION})"),
354
            )
355
            .into());
356
306
        }
357

            
358
        // The term with function symbol index 0 indicates the end of the stream
359
306
        let mut function_symbols = Protected::new(Vec::new());
360
306
        let end_of_stream_symbol = Symbol::new("end_of_stream".to_string(), 0);
361
306
        function_symbols.write().push(end_of_stream_symbol.copy());
362

            
363
306
        Ok(Self {
364
306
            stream,
365
306
            function_symbols,
366
306
            function_symbol_index_width: 1,
367
306
            terms: Protected::new(Vec::new()),
368
306
            term_index_width: 1,
369
306
            ended: false,
370
306
        })
371
306
    }
372

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

            
384
210352
        self.function_symbol_index_width
385
210352
    }
386

            
387
    /// Returns a mutable reference to the underlying bit stream reader.
388
    pub fn stream(&mut self) -> &mut BitStreamReader<R> {
389
        &mut self.stream
390
    }
391

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

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

            
416
        loop {
417
414322
            let header = self.stream.read_bits(PACKET_BITS)?;
418
414322
            let packet = PacketType::from(header as u8);
419
414322
            debug_trace!("Read packet: {:?}", packet);
420

            
421
414322
            match packet {
422
                PacketType::FunctionSymbol => {
423
2592
                    let name = self.stream.read_string()?;
424
2592
                    let arity = self.stream.read_integer()? as usize;
425
2592
                    let symbol = Symbol::new(name, arity);
426
2592
                    debug_trace!("Read symbol {symbol}");
427

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

            
447
210251
                    let symbols = self.function_symbols.read();
448
210251
                    let symbol = symbols.get(symbol_index).ok_or(format!(
449
                        "Read invalid function symbol index {symbol_index}, length {}",
450
210251
                        symbols.len()
451
                    ))?;
452

            
453
210251
                    if is_int_symbol(symbol) {
454
34
                        let value = self.stream.read_integer()?.try_into()?;
455
34
                        let term = ATermInt::new(value);
456
34
                        debug_trace!("Read int term: {term}");
457

            
458
34
                        let mut write_terms = self.terms.write();
459
34
                        let t = write_terms.protect(&term);
460
34
                        write_terms.push(t);
461
34
                        self.term_index_width = bits_for_value(write_terms.len());
462
                    } else {
463
                        // When the arity is zero, no bits are read for the arguments.
464
210217
                        let num_of_bits = if symbol.arity() > 0 { self.term_index_width() } else { 0 };
465
210217
                        let mut write_terms = self.terms.write();
466

            
467
210217
                        let term = ATerm::try_with_iter(
468
210217
                            symbol,
469
214884
                            (0..symbol.arity()).map(|_| {
470
214884
                                let arg_index = self.stream.read_bits(num_of_bits)? as usize;
471
214884
                                let arg = write_terms.get(arg_index).ok_or(format!(
472
                                    "Read invalid aterm index {arg_index}, length {}",
473
214884
                                    write_terms.len()
474
                                ))?;
475
214884
                                debug_trace!("Read arg: {arg}");
476
214884
                                Ok(arg)
477
214884
                            }),
478
                        )?;
479

            
480
210217
                        if packet == PacketType::ATermOutput {
481
206485
                            debug_trace!("Output term: {term}");
482
206485
                            return Ok(Some(term));
483
3732
                        }
484
3732
                        debug_trace!("Read term: {term}");
485

            
486
3732
                        let t = write_terms.protect(&term);
487
3732
                        write_terms.push(t);
488
3732
                        self.term_index_width = bits_for_value(write_terms.len());
489
                    }
490
                }
491
            }
492
        }
493
407964
    }
494

            
495
630
    fn read_aterm_iter(&mut self) -> Result<impl ExactSizeIterator<Item = Result<ATerm, MercError>>, MercError> {
496
630
        if self.ended {
497
            return Err(Error::new(
498
                ErrorKind::UnexpectedEof,
499
                "Attempted to read_aterm_iter() after end of stream",
500
            )
501
            .into());
502
630
        }
503

            
504
630
        let number_of_elements: ATermInt = self
505
630
            .read_aterm()?
506
630
            .ok_or("Missing number of elements for iterator")?
507
630
            .into();
508
630
        Ok(ATermReadIter {
509
630
            reader: self,
510
630
            remaining: number_of_elements.value(),
511
630
        })
512
630
    }
513
}
514

            
515
impl<R: Read> Drop for BinaryATermReader<R> {
516
306
    fn drop(&mut self) {
517
306
        self.function_symbols.write().clear();
518
306
        self.terms.write().clear();
519

            
520
        // Perform garbage collection after clearing the terms, since they might become unreachable.
521
306
        THREAD_TERM_POOL.with_borrow(|tp| tp.collect_garbage());
522
306
    }
523
}
524

            
525
impl<R: Read> BitStreamRead for BinaryATermReader<R> {
526
    delegate::delegate! {
527
        to self.stream {
528
32514
            fn read_bits(&mut self, number_of_bits: u8) -> Result<u64, MercError>;
529
            fn read_string(&mut self) -> Result<String, MercError>;
530
11100
            fn read_integer(&mut self) -> Result<u64, MercError>;
531
        }
532
    }
533
}
534

            
535
/// A read iterator for ATerms from a binary aterm input stream.
536
pub struct ATermReadIter<'a, R: Read> {
537
    reader: &'a mut BinaryATermReader<R>,
538
    remaining: usize,
539
}
540

            
541
impl<'a, R: Read> Iterator for ATermReadIter<'a, R> {
542
    type Item = Result<ATerm, MercError>;
543

            
544
2532
    fn next(&mut self) -> Option<Self::Item> {
545
2532
        if self.remaining == 0 {
546
530
            return None;
547
2002
        }
548

            
549
2002
        self.remaining -= 1;
550
2002
        match self.reader.read_aterm() {
551
2002
            Ok(Some(term)) => Some(Ok(term)),
552
            Ok(None) => Some(Err(Error::new(
553
                ErrorKind::UnexpectedEof,
554
                "Unexpected end of stream while reading iterator",
555
            )
556
            .into())),
557
            Err(e) => Some(Err(e)),
558
        }
559
2532
    }
560

            
561
1
    fn size_hint(&self) -> (usize, Option<usize>) {
562
1
        (self.remaining, Some(self.remaining))
563
1
    }
564
}
565

            
566
impl<'a, R: Read> ExactSizeIterator for ATermReadIter<'a, R> {
567
    fn len(&self) -> usize {
568
        self.remaining
569
    }
570
}
571

            
572
#[cfg(test)]
573
mod tests {
574
    use merc_utilities::random_test;
575

            
576
    use crate::ATermRead;
577
    use crate::ATermWrite;
578
    use crate::BinaryATermReader;
579
    use crate::BinaryATermWriter;
580
    use crate::random_term;
581

            
582
    #[test]
583
    #[cfg_attr(miri, ignore)] // Miri is too slow
584
1
    fn test_random_binary_stream() {
585
100
        random_test(100, |rng| {
586
100
            let input: Vec<_> = (0..20)
587
2000
                .map(|_| random_term(rng, &[("f".into(), 2), ("g".into(), 1)], &["a".into(), "b".into()], 1))
588
100
                .collect();
589

            
590
100
            let mut stream: Vec<u8> = Vec::new();
591

            
592
100
            let mut output_stream = BinaryATermWriter::new(&mut stream).unwrap();
593
2000
            for term in &input {
594
2000
                output_stream.write_aterm(term).unwrap();
595
2000
            }
596
100
            ATermWrite::flush(&mut output_stream).expect("Flushing the output to the stream");
597
100
            drop(output_stream); // Explicitly drop to release the mutable borrow
598

            
599
100
            let mut input_stream = BinaryATermReader::new(&stream[..]).unwrap();
600
2000
            for term in &input {
601
2000
                println!("Term {}", term);
602
2000
                debug_assert_eq!(
603
                    *term,
604
2000
                    input_stream.read_aterm().unwrap().unwrap(),
605
                    "The read term must match the term that we have written"
606
                );
607
            }
608
100
        });
609
1
    }
610

            
611
    #[test]
612
    #[cfg_attr(miri, ignore)] // Miri is too slow
613
1
    fn test_random_binary_stream_iter() {
614
100
        random_test(100, |rng| {
615
100
            let input: Vec<_> = (0..20)
616
2000
                .map(|_| random_term(rng, &[("f".into(), 2), ("g".into(), 1)], &["a".into(), "b".into()], 1))
617
100
                .collect();
618

            
619
100
            let mut stream: Vec<u8> = Vec::new();
620

            
621
100
            let mut output_stream = BinaryATermWriter::new(&mut stream).unwrap();
622
100
            output_stream.write_aterm_iter(input.iter().cloned()).unwrap();
623
100
            ATermWrite::flush(&mut output_stream).expect("Flushing the output to the stream");
624
100
            drop(output_stream); // Explicitly drop to release the mutable borrow
625

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