compressed writing
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 19 Jul 2025 21:14:34 +0000 (14:14 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 19 Jul 2025 21:14:34 +0000 (14:14 -0700)
rust/pspp/src/sys/write.rs

index 2ba55c2926815f62b2d551da519d39ec6869c481..356988fa1338e61734e2138b09fe8cd026b2cca0 100644 (file)
@@ -6,6 +6,7 @@ use std::{
     fmt::Write as _,
     fs::File,
     io::{BufWriter, Cursor, Seek, Write},
+    iter::repeat_n,
     path::Path,
 };
 
@@ -908,7 +909,60 @@ where
                     }
                 },
 
-                CaseVar::String { width: _, encoding } => todo!(),
+                CaseVar::String { width: _, encoding } => {
+                    let mut s = datum.as_string().unwrap().as_bytes();
+                    for segment in encoding {
+                        let data;
+                        (data, s) = s.split_at(segment.data_bytes);
+
+                        let (chunks, remainder) = data.as_chunks::<8>();
+                        for chunk in chunks {
+                            if chunk == b"        " {
+                                Self::put_opcode(
+                                    &mut self.opcodes,
+                                    &mut self.data,
+                                    &mut self.inner,
+                                    254,
+                                )?;
+                            } else {
+                                Self::put_opcode(
+                                    &mut self.opcodes,
+                                    &mut self.data,
+                                    &mut self.inner,
+                                    253,
+                                )?;
+                                self.data.extend_from_slice(chunk);
+                            }
+                        }
+                        if !remainder.is_empty() {
+                            if remainder.iter().all(|c| *c == b' ') {
+                                Self::put_opcode(
+                                    &mut self.opcodes,
+                                    &mut self.data,
+                                    &mut self.inner,
+                                    254,
+                                )?;
+                            } else {
+                                Self::put_opcode(
+                                    &mut self.opcodes,
+                                    &mut self.data,
+                                    &mut self.inner,
+                                    253,
+                                )?;
+                                self.data.extend_from_slice(remainder);
+                                self.data.extend(repeat_n(0, 8 - remainder.len()));
+                            }
+                        }
+                        for _ in 0..segment.padding_bytes / 8 {
+                            Self::put_opcode(
+                                &mut self.opcodes,
+                                &mut self.data,
+                                &mut self.inner,
+                                254,
+                            )?;
+                        }
+                    }
+                }
             }
         }
         Ok(())