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 formatted string if the serializer is human readable
39            // TODO(next): pad the output with leading zeros to make the result contains the correct precision
40            serializer.collect_str(self)
41        } else {
42            // otherwise serialize as a (significand, exponent, precision) struct
43            let mut se = serializer.serialize_struct("FBig", 3)?;
44            se.serialize_field(KEY_SIGNIF, &self.repr.significand)?;
45            se.serialize_field(KEY_EXPONENT, &self.repr.exponent)?;
46            se.serialize_field(KEY_PREC, &self.context.precision)?;
47            se.end()
48        }
49    }
50}
51
52struct ReprVisitor<const BASE: Word>;
53
54impl<'de, const B: Word> Visitor<'de> for ReprVisitor<B> {
55    type Value = Repr<B>;
56
57    #[inline]
58    fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
59        formatter.write_str("float repr as a literal string or a struct (significand, exponent)")
60    }
61
62    #[inline]
63    fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
64        #[allow(deprecated)] // TODO(v0.5): remove after from_str_native is made private.
65        match Repr::<B>::from_str_native(v) {
66            Ok((repr, _)) => Ok(repr),
67            Err(e) => Err(de::Error::custom(e)),
68        }
69    }
70
71    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
72        let err_report = || {
73            de::Error::invalid_length(
74                2,
75                &"a float repr consists of two integer fields: (significand, exponent)",
76            )
77        };
78        let significand = seq.next_element()?.ok_or_else(err_report)?;
79        let exponent = seq.next_element()?.ok_or_else(err_report)?;
80
81        if seq.next_element::<de::IgnoredAny>()?.is_some() {
82            Err(err_report())?
83        } else {
84            Ok(Repr::new(significand, exponent))
85        }
86    }
87
88    fn visit_map<A: serde::de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
89        let mut signif: Option<IBig> = None;
90        let mut exp: Option<isize> = None;
91        while let Some(key) = map.next_key()? {
92            match key {
93                KEY_SIGNIF => {
94                    if signif.is_some() {
95                        return Err(de::Error::duplicate_field(KEY_SIGNIF));
96                    }
97                    signif = Some(map.next_value()?);
98                }
99                KEY_EXPONENT => {
100                    if exp.is_some() {
101                        return Err(de::Error::duplicate_field(KEY_EXPONENT));
102                    }
103                    exp = Some(map.next_value()?);
104                }
105                _ => return Err(de::Error::unknown_field(key, REPR_FIELDS)),
106            }
107        }
108
109        let significand = signif.ok_or_else(|| de::Error::missing_field(KEY_SIGNIF))?;
110        let exponent = exp.ok_or_else(|| de::Error::missing_field(KEY_EXPONENT))?;
111        Ok(Repr::new(significand, exponent))
112    }
113}
114
115impl<'de, const B: Word> Deserialize<'de> for Repr<B> {
116    #[inline]
117    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
118        if deserializer.is_human_readable() {
119            deserializer.deserialize_str(ReprVisitor)
120        } else {
121            deserializer.deserialize_struct("FBigRepr", REPR_FIELDS, ReprVisitor)
122        }
123    }
124}
125
126struct FBigVisitor<RoundingMode: Round, const BASE: Word>(PhantomData<RoundingMode>);
127
128impl<'de, R: Round, const B: Word> Visitor<'de> for FBigVisitor<R, B> {
129    type Value = FBig<R, B>;
130
131    #[inline]
132    fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
133        formatter.write_str(
134            "float number as a literal string or a struct (significand, exponent, precision)",
135        )
136    }
137
138    #[inline]
139    fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
140        #[allow(deprecated)] // TODO(v0.5): remove after from_str_native is made private.
141        FBig::from_str_native(v).map_err(de::Error::custom)
142    }
143
144    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
145        let err_report = || {
146            de::Error::invalid_length(2,
147            &"a float number consists of three integer fields: (significand, exponent, precision)")
148        };
149        let significand = seq.next_element()?.ok_or_else(err_report)?;
150        let exponent = seq.next_element()?.ok_or_else(err_report)?;
151        let precision = seq.next_element()?.ok_or_else(err_report)?;
152
153        if seq.next_element::<de::IgnoredAny>()?.is_some() {
154            Err(err_report())?
155        } else {
156            Ok(FBig {
157                repr: Repr::new(significand, exponent),
158                context: Context::new(precision),
159            })
160        }
161    }
162
163    fn visit_map<A: serde::de::MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
164        let mut signif: Option<IBig> = None;
165        let mut exp: Option<isize> = None;
166        let mut prec: Option<usize> = None;
167        while let Some(key) = map.next_key()? {
168            match key {
169                KEY_SIGNIF => {
170                    if signif.is_some() {
171                        return Err(de::Error::duplicate_field(KEY_SIGNIF));
172                    }
173                    signif = Some(map.next_value()?);
174                }
175                KEY_EXPONENT => {
176                    if exp.is_some() {
177                        return Err(de::Error::duplicate_field(KEY_EXPONENT));
178                    }
179                    exp = Some(map.next_value()?);
180                }
181                KEY_PREC => {
182                    if prec.is_some() {
183                        return Err(de::Error::duplicate_field(KEY_PREC));
184                    }
185                    prec = Some(map.next_value()?);
186                }
187                _ => return Err(de::Error::unknown_field(key, REPR_FIELDS)),
188            }
189        }
190
191        let significand = signif.ok_or_else(|| de::Error::missing_field(KEY_SIGNIF))?;
192        let exponent = exp.ok_or_else(|| de::Error::missing_field(KEY_EXPONENT))?;
193        let precision = prec.ok_or_else(|| de::Error::missing_field(KEY_PREC))?;
194        Ok(FBig {
195            repr: Repr::new(significand, exponent),
196            context: Context::new(precision),
197        })
198    }
199}
200
201impl<'de, R: Round, const B: Word> Deserialize<'de> for FBig<R, B> {
202    #[inline]
203    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
204        if deserializer.is_human_readable() {
205            deserializer.deserialize_str(FBigVisitor(PhantomData))
206        } else {
207            deserializer.deserialize_struct("FBig", FBIG_FIELDS, FBigVisitor(PhantomData))
208        }
209    }
210}