tawasuyu

tawasuyu/brahman

Rust 334TOML 129Markdown 39JSON 174745 Definiciones

⎇ 85156c15090f0ae5116737b7c07cddae23cbf7f3 crates/modules/charka/charka-runtime/src/text.rs Rust · 110 líneas · 2.8 KB Historia Quién tocó qué crudo

feat(charka): charka-runtime — soporte de ejecución (campos Num y Text) 85156c150 · sergio ·

1//! `Text` — un campo alfanumérico COBOL en tiempo de ejecución.
2
3/// Un campo alfanumérico de longitud fija (`PIC X(n)`). El contenido
4/// se mantiene siempre con exactamente `len` caracteres — toda
5/// asignación justifica a la izquierda y rellena o trunca.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Text {
8    buf: String,
9    len: usize,
10}
11
12impl Text {
13    /// Campo nuevo de `len` caracteres, lleno de espacios.
14    pub fn new(len: usize) -> Self {
15        Self {
16            buf: " ".repeat(len),
17            len,
18        }
19    }
20
21    /// Campo con un `VALUE` inicial.
22    pub fn with_value(len: usize, literal: &str) -> Self {
23        let mut t = Self::new(len);
24        t.store(literal);
25        t
26    }
27
28    /// Asigna un texto: lo justifica a la izquierda, y rellena con
29    /// espacios o trunca hasta `len` — el `MOVE` alfanumérico de COBOL.
30    pub fn store(&mut self, s: &str) {
31        let mut chars: Vec<char> = s.chars().take(self.len).collect();
32        while chars.len() < self.len {
33            chars.push(' ');
34        }
35        self.buf = chars.into_iter().collect();
36    }
37
38    /// Llena el campo entero con un carácter — para mover las
39    /// constantes figurativas (`SPACES`, `ZEROS`...).
40    pub fn fill(&mut self, ch: char) {
41        self.buf = (0..self.len).map(|_| ch).collect();
42    }
43
44    /// El contenido actual (siempre exactamente `len` caracteres).
45    pub fn as_str(&self) -> &str {
46        &self.buf
47    }
48
49    /// La longitud declarada del campo.
50    pub fn len(&self) -> usize {
51        self.len
52    }
53
54    /// ¿El campo se declaró con longitud cero?
55    pub fn is_empty(&self) -> bool {
56        self.len == 0
57    }
58
59    /// Representación para `DISPLAY` — el contenido tal cual, con sus
60    /// espacios de relleno incluidos.
61    pub fn display(&self) -> String {
62        self.buf.clone()
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn new_field_is_all_spaces() {
72        let t = Text::new(5);
73        assert_eq!(t.as_str(), "     ");
74        assert_eq!(t.len(), 5);
75    }
76
77    #[test]
78    fn with_value_left_justifies_and_pads() {
79        let t = Text::with_value(5, "AB");
80        assert_eq!(t.as_str(), "AB   ");
81    }
82
83    #[test]
84    fn store_truncates_when_too_long() {
85        let mut t = Text::new(3);
86        t.store("HELLO");
87        assert_eq!(t.as_str(), "HEL");
88    }
89
90    #[test]
91    fn store_pads_when_too_short() {
92        let mut t = Text::new(6);
93        t.store("HI");
94        assert_eq!(t.as_str(), "HI    ");
95    }
96
97    #[test]
98    fn fill_sets_every_position() {
99        let mut t = Text::new(4);
100        t.fill('0');
101        assert_eq!(t.as_str(), "0000");
102    }
103
104    #[test]
105    fn zero_length_field_is_empty() {
106        let t = Text::new(0);
107        assert!(t.is_empty());
108        assert_eq!(t.as_str(), "");
109    }
110}