ptero/method/
trailing_whitespace.rs

1//! # Description
2//!
3//! This method uses the trailing [ASCII_WHITESPACE] to encode bits.
4//! If the whitespace is present the bit 1 is encoded, otherwise 0.
5//!
6//! This method provides both encoding and decoding algorithm.
7
8use std::error::Error;
9
10use log::trace;
11
12use crate::{
13    binary::Bit,
14    context::{Context, ContextError},
15    decoder::Decoder,
16    encoder::{Capacity, Encoder, EncoderResult},
17};
18
19/// Character used as the trailing whitespace in the method.
20pub const ASCII_WHITESPACE: char = ' ';
21
22use super::Method;
23// Unit structure used to define the method.
24// Implements both [Encoder](crate::encoder::Encode) and [Decoder](crate::decoder::Decoder) traits.
25// Accepts any [Context](crate::context::Context).
26#[derive(Debug, PartialEq)]
27pub struct TrailingWhitespaceMethod;
28
29impl Default for TrailingWhitespaceMethod {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl TrailingWhitespaceMethod {
36    pub fn new() -> Self {
37        TrailingWhitespaceMethod {}
38    }
39}
40
41impl Capacity for TrailingWhitespaceMethod {
42    fn bitrate(&self) -> usize {
43        1
44    }
45}
46
47impl<E> Encoder<E> for TrailingWhitespaceMethod
48where
49    E: Context,
50{
51    fn partial_encode(
52        &self,
53        context: &mut E,
54        data: &mut dyn Iterator<Item = Bit>,
55    ) -> Result<EncoderResult, Box<dyn Error>> {
56        Ok(match data.next() {
57            Some(Bit(1)) => {
58                trace!("Putting whitespace at the end of the line");
59                context.get_current_text_mut()?.push(ASCII_WHITESPACE);
60                EncoderResult::Success
61            }
62            None => EncoderResult::NoDataLeft,
63            _ => {
64                trace!("Skipping trailing whitespace");
65                EncoderResult::Success
66            }
67        })
68    }
69}
70
71impl<D> Decoder<D> for TrailingWhitespaceMethod
72where
73    D: Context,
74{
75    fn partial_decode(&self, context: &D) -> Result<Vec<Bit>, ContextError> {
76        let bit = if context.get_current_text()?.ends_with(ASCII_WHITESPACE) {
77            trace!("Found trailing whitespace");
78            Bit(1)
79        } else {
80            trace!("No trailing whitespace");
81            Bit(0)
82        };
83        Ok(vec![bit])
84    }
85}
86
87impl<E, D> Method<E, D> for TrailingWhitespaceMethod
88where
89    E: Context,
90    D: Context,
91{
92    fn method_name(&self) -> String {
93        "TrailingWhitespaceMethod".to_string()
94    }
95}