⎇ 85156c15090f0ae5116737b7c07cddae23cbf7f3
crates/modules/charka/charka-runtime/src/text.rs
Ñawpa willay
Pi imata llamkarqan
ch'uya
feat(charka): charka-runtime — soporte de ejecución (campos Num y Text)
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}