Skip to main content

dashu_float/third_party/
serde.rs

1//! Implement serde traits.
2
3use core::marker::PhantomData;
4
5use crate::{fbig::FBig, repr::Repr, round::Round, Context};
6use dashu_int::{IBig, Word};
7use serde::{
8    de::{self, Deserialize, Deserializer, SeqAccess, Visitor},
9    ser::{Serialize, SerializeStruct, Serializer},
10};
11
12const KEY_SIGNIF: &str = "significand";
13const KEY_EXPONENT: &str = "exponent";
14const KEY_PREC: &str = "precision";
15const REPR_FIELDS: &[&str] = &[KEY_SIGNIF, KEY_EXPONENT];
16const FBIG_FIELDS: &[&str] = &[KEY_SIGNIF, KEY_EXPONENT, KEY_PREC];
17
18impl<const B: Word> Serialize for Repr<B> {
19    #[inline]
20    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
21        if serializer.is_human_readable() {
22            // serialize to formatted string if the serializer is human readable
23            serializer.collect_str(self)
24        } else {
25            // otherwise serialize as a (significand, exponent) struct
26            let mut se = serializer.serialize_struct("FBigRepr", 2)?;
27            se.serialize_field(KEY_SIGNIF, &self.significand)?;
28            se.serialize_field(KEY_EXPONENT, &self.exponent)?;
29            se.end()
30        }
31    }
32}
33
34impl<R: Round, const B: Word> Serialize for FBig<R, B> {
35    #[inline]
36    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
37        if serializer.is_human_readable() {
38            // Serialize to a formatted string, padding it with trailing zeros so the
39            // number of digit characters equals the context precision. The deserializer
40            // re-infers precision from that digit count, so this lets precision round-trip
41            // through the human-readable format.
42            if self.repr.is_infinite() {
43                serializer.collect_str(self)
44            } else {
45                let mut s = alloc::format!("{}", self);
46                let digits = s.bytes().filter(|b| b.is_ascii_digit()).count();
47                if digits < self.context.precision {
48                    let need = self.context.precision - digits;
49                    if s.contains('.') {
50                        s.extend(core::iter::repeat('0').take(need));
51                    } else {
52                        s.push('.');
53                        s.extend(core::iter::repeat('0').take(need));
54                    }
55                }
56                serializer.serialize_str(&s)
57            }
58        } else {
59            // otherwise serialize as a (significand, exponent, precision) struct
60            let mut se = serializer.serialize_struct("FBig", 3)?;
61            se.serialize_field(KEY_SIGNIF, &self.repr.significand)?;
62            se.serialize_field(KEY_EXPONENT, &self.repr.exponent)?;
63            se.serialize_field(KEY_PREC, &self.context.precision)?;
64            se.end()
65        }
66    }
67}
68
69struct ReprVisitor<const BASE: Word>;
70
71impl<'de, const B: Word> Visitor<'de> for ReprVisitor<B> {
72    type Value = Repr<B>;
73
74    #[inline]
75    fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
76        formatter.write_str("float repr as a literal string or a struct (significand, exponent)")
77    }
78
79    #[inline]
80    fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
81        match Repr::<B>::from_str_native(v) {
82            Ok((repr, _)) => Ok(repr),
83            Err(e) => Err(de::Error::custom(e)),
84        }
85    }
86
87    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
88        let err_report = || {
89            de::Error::invalid_length(
90                2,
91                &"a float repr consists of two integer fields: (significand, exponent)",
92            )
93        };
94        let significand = seq.next_element()?.ok_or_else(err_report)?;
95        let exponent = seq.next_element()?.ok_or_else(err_report)?;
96
97        if seq.next_element::<de::IgnoredAny>()?.is_some() {
98            Err(err_report())?
99        } else {
100            Ok(Repr::new(significand, exponent))
101        }
102    }
103
104    fn visit_map<A: serde::de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
105        let mut signif: Option<IBig> = None;
106        let mut exp: Option<isize> = None;
107        while let Some(key) = map.next_key()? {
108            match key {
109                KEY_SIGNIF => {
110                    if signif.is_some() {
111                        return Err(de::Error::duplicate_field(KEY_SIGNIF));
112                    }
113                    signif = Some(map.next_value()?);
114                }
115                KEY_EXPONENT => {
116                    if exp.is_some() {
117                        return Err(de::Error::duplicate_field(KEY_EXPONENT));
118                    }
119                    exp = Some(map.next_value()?);
120                }
121                _ => return Err(de::Error::unknown_field(key, REPR_FIELDS)),
122            }
123        }
124
125        let significand = signif.ok_or_else(|| de::Error::missing_field(KEY_SIGNIF))?;
126        let exponent = exp.ok_or_else(|| de::Error::missing_field(KEY_EXPONENT))?;
127        Ok(Repr::new(significand, exponent))
128    }
129}
130
131impl<'de, const B: Word> Deserialize<'de> for Repr<B> {
132    #[inline]
133    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
134        if deserializer.is_human_readable() {
135            deserializer.deserialize_str(ReprVisitor)
136        } else {
137            deserializer.deserialize_struct("FBigRepr", REPR_FIELDS, ReprVisitor)
138        }
139    }
140}
141
142struct FBigVisitor<RoundingMode: Round, const BASE: Word>(PhantomData<RoundingMode>);
143
144impl<'de, R: Round, const B: Word> Visitor<'de> for FBigVisitor<R, B> {
145    type Value = FBig<R, B>;
146
147    #[inline]
148    fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
149        formatter.write_str(
150            "float number as a literal string or a struct (significand, exponent, precision)",
151        )
152    }
153
154    #[inline]
155    fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
156        let (repr, ndigits) = Repr::<B>::from_str_native(v).map_err(de::Error::custom)?;
157        Ok(FBig {
158            repr,
159            context: Context::new(ndigits),
160        })
161    }
162
163    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
164        let err_report = || {
165            de::Error::invalid_length(2,
166            &"a float number consists of three integer fields: (significand, exponent, precision)")
167        };
168        let significand = seq.next_element()?.ok_or_else(err_report)?;
169        let exponent = seq.next_element()?.ok_or_else(err_report)?;
170        let precision = seq.next_element()?.ok_or_else(err_report)?;
171
172        if seq.next_element::<de::IgnoredAny>()?.is_some() {
173            Err(err_report())?
174        } else {
175            Ok(FBig {
176                repr: Repr::new(significand, exponent),
177                context: Context::new(precision),
178            })
179        }
180    }
181
182    fn visit_map<A: serde::de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
183        let mut signif: Option<IBig> = None;
184        let mut exp: Option<isize> = None;
185        let mut prec: Option<usize> = None;
186        while let Some(key) = map.next_key()? {
187            match key {
188                KEY_SIGNIF => {
189                    if signif.is_some() {
190                        return Err(de::Error::duplicate_field(KEY_SIGNIF));
191                    }
192                    signif = Some(map.next_value()?);
193                }
194                KEY_EXPONENT => {
195                    if exp.is_some() {
196                        return Err(de::Error::duplicate_field(KEY_EXPONENT));
197                    }
198                    exp = Some(map.next_value()?);
199                }
200                KEY_PREC => {
201                    if prec.is_some() {
202                        return Err(de::Error::duplicate_field(KEY_PREC));
203                    }
204                    prec = Some(map.next_value()?);
205                }
206                _ => return Err(de::Error::unknown_field(key, REPR_FIELDS)),
207            }
208        }
209
210        let significand = signif.ok_or_else(|| de::Error::missing_field(KEY_SIGNIF))?;
211        let exponent = exp.ok_or_else(|| de::Error::missing_field(KEY_EXPONENT))?;
212        let precision = prec.ok_or_else(|| de::Error::missing_field(KEY_PREC))?;
213        Ok(FBig {
214            repr: Repr::new(significand, exponent),
215            context: Context::new(precision),
216        })
217    }
218}
219
220impl<'de, R: Round, const B: Word> Deserialize<'de> for FBig<R, B> {
221    #[inline]
222    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
223        if deserializer.is_human_readable() {
224            deserializer.deserialize_str(FBigVisitor(PhantomData))
225        } else {
226            deserializer.deserialize_struct("FBig", FBIG_FIELDS, FBigVisitor(PhantomData))
227        }
228    }
229}