1use numeric::Numproc;
5use crate::vocab::{SignClause, SignPosition};
6use zarch::check::ProgramCheck;
7use zarch::decimal::{self, Decimal};
8
9pub fn packed(bytes: &[u8], signed: bool, numproc: Numproc) -> Result<Decimal, ProgramCheck> {
11 let mut p = bytes.to_vec();
12 if !signed && numproc == Numproc::Nopfd {
13 *p.last_mut().unwrap() |= 0x0F;
14 }
15 decimal::decode(&p)
16}
17
18pub fn zoned(bytes: &[u8], signed: bool, sign: Option<SignClause>, numproc: Numproc) -> Result<Decimal, ProgramCheck> {
20 let mut zoned = bytes.to_vec();
21 let mut separate_negative = None;
22 match sign {
23 Some(SignClause { separate: true, position }) => {
24 let s = if position == SignPosition::Leading { zoned.remove(0) } else { zoned.pop().unwrap() };
25 separate_negative = Some(match s {
26 0x60 => true,
27 0x4E => false,
28 _ => return Err(ProgramCheck::Data),
29 });
30 *zoned.last_mut().unwrap() |= 0xF0;
31 }
32 Some(SignClause { separate: false, position: SignPosition::Leading }) => {
33 let zone = zoned[0] & 0xF0;
34 zoned[0] |= 0xF0;
35 let last = zoned.len() - 1;
36 zoned[last] = zone | (zoned[last] & 0x0F);
37 }
38 _ => {}
39 }
40 let p = numeric::zoned::pack(&zoned)?;
41 let value = packed(&p, signed, numproc)?;
42 Ok(match separate_negative {
43 Some(negative) => Decimal { negative, ..value },
44 None => value,
45 })
46}