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
3802760
    fn from(value: u8) -> Self {
66
3802760
        match value {
67
17000
            0 => PacketType::FunctionSymbol,
68
29790
            1 => PacketType::ATerm,
69
1884270
            2 => PacketType::ATermOutput,
70
1871700
            3 => PacketType::ATermIntOutput,
71
            _ => panic!("Invalid packet type: {value}"),
72
        }
73
3802760
    }
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
192464
    fn write_function_symbol(&mut self, symbol: &SymbolRef<'_>) -> Result<usize, MercError> {
179
192464
        let (index, inserted) = self.function_symbols.insert(symbol.protect());
180

            
181
192464
        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
190264
        }
188

            
189
192464
        Ok(*index)
190
192464
    }
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
192764
    fn function_symbol_index_width(&self) -> u8 {
197
192764
        let expected = bits_for_value(self.function_symbols.len());
198
192764
        debug_assert_eq!(
199
            self.function_symbol_index_width, expected,
200
            "function_symbol_index_width does not match bits_for_value",
201
        );
202

            
203
192764
        self.function_symbol_index_width
204
192764
    }
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
193897
    fn term_index_width(&self) -> u8 {
211
193897
        let expected = bits_for_value(self.terms.len());
212
193897
        debug_assert_eq!(
213
            self.term_index_width, expected,
214
            "term_index_width does not match bits_for_value",
215
        );
216
193897
        self.term_index_width
217
193897
    }
218
}
219

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

            
224
1136972
        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
759144
            let is_output = self.stack.is_empty();
227

            
228
759144
            if !self.terms.contains(&current_term) || is_output {
229
759056
                if write_ready {
230
379528
                    if is_int_term(&current_term) {
231
187064
                        let int_term = ATermIntRef::from(current_term.copy());
232
187064
                        if is_output {
233
                            // If the integer is output, write the header and just an integer
234
187064
                            self.stream.write_bits(PacketType::ATermIntOutput as u64, PACKET_BITS)?;
235
187064
                            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
192464
                        let symbol_index = self.write_function_symbol(&current_term.get_head_symbol())?;
246
192464
                        let packet_type = if is_output {
247
190764
                            PacketType::ATermOutput
248
                        } else {
249
1700
                            PacketType::ATerm
250
                        };
251

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

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

            
262
379528
                    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
377828
                    }
267
                } else {
268
                    // Add current term back to stack for writing after processing arguments
269
379528
                    self.stack.push_back((current_term.clone(), true));
270

            
271
                    // Add arguments to stack for processing first
272
381061
                    for arg in current_term.arguments() {
273
193897
                        if !self.terms.contains(&arg) {
274
1788
                            self.stack.push_back((arg.protect(), false));
275
192109
                        }
276
                    }
277
                }
278
88
            }
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
377828
        Ok(())
285
377828
    }
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
302
    pub fn new(reader: R) -> Result<Self, MercError> {
346
302
        let mut stream = BitStreamReader::new(reader);
347

            
348
        // Read the binary aterm format header
349
302
        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
302
        }
352

            
353
302
        let version = stream.read_bits(16)?;
354
302
        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
302
        }
361

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

            
367
302
        Ok(Self {
368
302
            stream,
369
302
            function_symbols,
370
302
            function_symbol_index_width: 1,
371
302
            terms: Protected::new(Vec::new()),
372
302
            term_index_width: 1,
373
302
            ended: false,
374
302
        })
375
302
    }
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
195366
    fn function_symbol_index_width(&self) -> u8 {
382
195366
        let expected = bits_for_value(self.function_symbols.read().len());
383
195366
        debug_assert_eq!(
384
            self.function_symbol_index_width, expected,
385
            "function_symbol_index_width does not match bits_for_value",
386
        );
387

            
388
195366
        self.function_symbol_index_width
389
195366
    }
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
100480
    fn term_index_width(&self) -> u8 {
401
100480
        let expected = bits_for_value(self.terms.read().len());
402
100480
        debug_assert_eq!(
403
            self.term_index_width, expected,
404
            "term_index_width does not match bits_for_value",
405
        );
406
100480
        self.term_index_width
407
100480
    }
408
}
409

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

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

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

            
432
2420
                    let mut write_symbols = self.function_symbols.write();
433
2420
                    let s = write_symbols.protect_symbol(&symbol);
434
2420
                    write_symbols.push(s);
435
2420
                    self.function_symbol_index_width = bits_for_value(write_symbols.len());
436
                }
437
                PacketType::ATermIntOutput => {
438
187260
                    let value = self.stream.read_integer()?.try_into()?;
439
187260
                    debug_trace!("Output int term: {}", ATermInt::new(value));
440
187260
                    return Ok(Some(ATermInt::new(value).into()));
441
                }
442
                PacketType::ATerm | PacketType::ATermOutput => {
443
195366
                    let symbol_index = self.stream.read_bits(self.function_symbol_index_width())? as usize;
444
195366
                    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
195265
                    }
450

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

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

            
462
18
                        let mut write_terms = self.terms.write();
463
18
                        let t = write_terms.protect(&term);
464
18
                        write_terms.push(t);
465
18
                        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
195247
                        let num_of_bits = if symbol.arity() > 0 { self.term_index_width() } else { 0 };
469
195247
                        let mut write_terms = self.terms.write();
470
199223
                        for _ in 0..symbol.arity() {}
471

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

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

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

            
500
610
    fn read_aterm_iter(&mut self) -> Result<impl ExactSizeIterator<Item = Result<ATerm, MercError>>, MercError> {
501
610
        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
610
        }
508

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

            
520
impl<R: Read> BitStreamRead for BinaryATermReader<R> {
521
    delegate::delegate! {
522
        to self.stream {
523
29230
            fn read_bits(&mut self, number_of_bits: u8) -> Result<u64, MercError>;
524
            fn read_string(&mut self) -> Result<String, MercError>;
525
9908
            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
2512
    fn next(&mut self) -> Option<Self::Item> {
540
2512
        if self.remaining == 0 {
541
510
            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
2512
    }
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
1
    fn test_random_binary_stream() {
577
100
        random_test(100, |rng| {
578
100
            let input: Vec<_> = (0..20)
579
2000
                .map(|_| random_term(rng, &[("f".into(), 2), ("g".into(), 1)], &["a".into(), "b".into()], 1))
580
100
                .collect();
581

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

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

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

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

            
610
100
            let mut stream: Vec<u8> = Vec::new();
611

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

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