};
use chrono::{Datelike, Local, NaiveDate};
-use encoding_rs::Encoding;
+use encoding_rs::{Encoding, UTF_8};
use enum_iterator::{all, Sequence};
use enum_map::{Enum, EnumMap};
use libm::frexp;
Type::N => self.n(f, number),
Type::Z => self.z(f, number),
- Type::P => todo!(),
- Type::PK => todo!(),
- Type::IB => todo!(),
- Type::PIB => todo!(),
- Type::RB => todo!(),
+ Type::P | Type::PK | Type::IB | Type::PIB | Type::RB => self.fmt_binary(f),
Type::PIBHex => self.pibhex(f, number),
Type::RBHex => self.rbhex(f, number),
pub fn with_settings(self, settings: &'b Settings) -> Self {
Self { settings, ..self }
}
+ fn fmt_binary(&self, f: &mut Formatter) -> FmtResult {
+ let output = self.to_binary().unwrap();
+ for b in output {
+ f.write_char(b as char)?;
+ }
+ Ok(())
+ }
fn number(&self, f: &mut Formatter<'_>, number: f64) -> FmtResult {
if number.is_finite() {
let style = self.settings.number_style(self.format.type_);
fn missing(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.format.type_ {
- //Type::P => return self.p(f, -f64::MAX),
+ Type::P | Type::PK | Type::IB | Type::PIB | Type::RB => return self.fmt_binary(f),
Type::RBHex => return self.rbhex(f, -f64::MAX),
_ => (),
}
}
}
- pub fn write_binary<W>(&self, w: W) -> Result<bool, IoError>
+ /// Writes this object to `w`. Writes binary formats ([Type::P],
+ /// [Type::PIB], and so on) as binary values, and writes other output
+ /// formats in the given `encoding`.
+ ///
+ /// If `dv` is a [DisplayValue], the difference between `write!(f, "{}",
+ /// dv)` and `dv.write(f, encoding)` is:
+ ///
+ /// * `write!` always outputs UTF-8. Binary formats are encoded as the
+ /// Unicode characters corresponding to their bytes.
+ ///
+ /// * `dv.write` outputs the desired `encoding`. Binary formats are not
+ /// encoded in `encoding` (and thus they might be invalid for the
+ /// encoding).
+ pub fn write<W>(&self, mut w: W, encoding: &'static Encoding) -> Result<(), IoError>
where
W: IoWrite,
{
- let Some(number) = self.value.as_number() else {
- return Ok(false);
- };
+ match self.to_binary() {
+ Some(binary) => w.write_all(&binary),
+ None if encoding == UTF_8 => {
+ write!(&mut w, "{}", self)
+ }
+ None => {
+ let mut temp = SmallString::<[u8; 64]>::new();
+ write!(&mut temp, "{}", self).unwrap();
+ w.write_all(&encoding.encode(&temp).0)
+ }
+ }
+ }
+
+ fn to_binary(&self) -> Option<SmallVec<[u8; 16]>> {
+ let number = self.value.as_number()?;
match self.format.type_() {
- Type::P => self.p(w, number).map(|()| true),
- Type::PK => self.pk(w, number).map(|()| true),
- _ => Ok(false),
+ Type::P => Some(self.p(number)),
+ Type::PK => Some(self.pk(number)),
+ _ => None,
}
}
}
}
- fn p<W>(&self, mut w: W, number: Option<f64>) -> Result<(), IoError>
- where
- W: IoWrite,
- {
+ fn p(&self, number: Option<f64>) -> SmallVec<[u8; 16]> {
let (valid, mut output) = self.bcd(number, self.format.w() * 2 - 1);
if valid && number.is_some_and(|number| number < 0.0) {
*output.last_mut().unwrap() |= 0xd;
} else {
*output.last_mut().unwrap() |= 0xf;
}
- w.write_all(&*output)
+ output
}
- fn pk<W>(&self, mut w: W, number: Option<f64>) -> Result<(), IoError>
- where
- W: IoWrite,
- {
+ fn pk(&self, number: Option<f64>) -> SmallVec<[u8; 16]> {
let number = match number {
Some(number) if number < 0.0 => None,
other => other,
};
let (_valid, output) = self.bcd(number, self.format.w() * 2);
- w.write_all(&*output)
+ output
}
}
assert_eq!(tokens.get(1), Some(&Token::Punct(Punct::Colon)));
let expected = tokens[2].as_string().unwrap();
let mut actual = SmallVec::<[u8; 16]>::new();
- assert!(Value::Number(value)
+ Value::Number(value)
.display(format, UTF_8)
- .write_binary(&mut actual)
- .unwrap());
+ .write(&mut actual, UTF_8)
+ .unwrap();
let mut actual_s = SmallString::<[u8; 32]>::new();
for b in actual {
write!(&mut actual_s, "{:02x}", b).unwrap();