use crate::constants::NumericArrayEnum;
use crate::writer::Writer;
use crate::wxf::writer::WxfWriter;
use crate::Error;
pub trait ToWXF {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error>;
}
pub trait WxfStruct {}
macro_rules! impl_to_wxf_int {
($($t:ty),+) => {
$(
impl ToWXF for $t {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_integer(i64::from(*self))
}
}
)+
};
}
impl_to_wxf_int!(i8, i16, i32, i64, u8, u16, u32);
impl ToWXF for u64 {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_integer(i64::try_from(*self).unwrap_or(i64::MAX))
}
}
impl ToWXF for f32 {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_real(f64::from(*self))
}
}
impl ToWXF for f64 {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_real(*self)
}
}
impl ToWXF for bool {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_symbol(if *self { "System`True" } else { "System`False" })
}
}
impl ToWXF for str {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_string(self)
}
}
impl ToWXF for String {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_string(self.as_str())
}
}
impl<T: ToWXF + ?Sized> ToWXF for &T {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
(*self).to_wxf(w)
}
}
impl<T: ToWXF + ?Sized> ToWXF for Box<T> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
(**self).to_wxf(w)
}
}
impl ToWXF for [u8] {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_byte_array(self)
}
}
impl ToWXF for Vec<u8> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_byte_array(self)
}
}
macro_rules! impl_slice_numeric {
($($t:ty => $variant:ident),+ $(,)?) => {
$(
impl ToWXF for [$t] {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
let bytes: &[u8] = unsafe {
::core::slice::from_raw_parts(
self.as_ptr() as *const u8,
::core::mem::size_of::<$t>() * self.len(),
)
};
w.write_numeric_array(NumericArrayEnum::$variant, &[self.len()], bytes)
}
}
impl ToWXF for Vec<$t> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
self.as_slice().to_wxf(w)
}
}
)+
};
}
impl_slice_numeric!(
i8 => Integer8,
i16 => Integer16,
i32 => Integer32,
i64 => Integer64,
u16 => UnsignedInteger16,
u32 => UnsignedInteger32,
u64 => UnsignedInteger64,
f32 => Real32,
f64 => Real64,
);
impl<T: ToWXF + WxfStruct> ToWXF for Vec<T> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_function(self.len())?;
w.write_symbol("System`List")?;
for e in self {
e.to_wxf(w)?;
}
Ok(())
}
}
impl ToWXF for () {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_symbol("System`Null")
}
}
impl<T: ToWXF> ToWXF for Option<T> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
match self {
None => crate::strategy::write_unit_variant(
w,
crate::strategy::DEFAULT_ENUM_HEAD,
"None",
),
Some(v) => {
crate::strategy::begin_data_variant(
w,
crate::strategy::DEFAULT_ENUM_HEAD,
"Some",
1,
)?;
v.to_wxf(w)
},
}
}
}
impl<T: ToWXF, E: ToWXF> ToWXF for Result<T, E> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
match self {
Ok(v) => {
crate::strategy::begin_data_variant(
w,
crate::strategy::DEFAULT_ENUM_HEAD,
"Ok",
1,
)?;
v.to_wxf(w)
},
Err(e) => {
crate::strategy::begin_data_variant(
w,
crate::strategy::DEFAULT_ENUM_HEAD,
"Err",
1,
)?;
e.to_wxf(w)
},
}
}
}
impl<K: ToWXF, V: ToWXF, S> ToWXF for std::collections::HashMap<K, V, S> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_association(self.len())?;
for (k, v) in self {
w.write_rule(false)?;
k.to_wxf(w)?;
v.to_wxf(w)?;
}
Ok(())
}
}
impl<K: ToWXF, V: ToWXF> ToWXF for std::collections::BTreeMap<K, V> {
fn to_wxf<W: Writer>(&self, w: &mut WxfWriter<W>) -> Result<(), Error> {
w.write_association(self.len())?;
for (k, v) in self {
w.write_rule(false)?;
k.to_wxf(w)?;
v.to_wxf(w)?;
}
Ok(())
}
}