1use core::str::FromStr;
24
25use amplify::confinement::TinyBlob;
26use amplify::hex::FromHex;
27use amplify::num::u256;
28use amplify::{hex, Bytes32, Wrapper};
29use strict_encoding::{StrictDecode, StrictProduct, StrictTuple, StrictType, TypeName};
30
31use crate::LIB_NAME_FINITE_FIELD;
32
33#[allow(non_camel_case_types)]
37#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, From)]
38#[display("{0:X}.fe", alt = "{0:064X}.fe")]
39#[derive(StrictDumb, StrictEncode, StrictDecode)]
40#[strict_type(lib = LIB_NAME_FINITE_FIELD)]
41pub struct fe256(
42    #[from(u8)]
43    #[from(u16)]
44    #[from(u32)]
45    #[from(u64)]
46    #[from(u128)]
47    u256,
48);
49
50impl fe256 {
51    pub const ZERO: Self = Self(u256::ZERO);
53
54    pub const fn to_u256(&self) -> u256 { self.0 }
56}
57
58impl From<Bytes32> for fe256 {
59    fn from(bytes: Bytes32) -> Self { Self::from(bytes.into_inner()) }
60}
61
62impl From<[u8; 32]> for fe256 {
63    fn from(bytes: [u8; 32]) -> Self {
64        let val = u256::from_le_bytes(bytes);
65        Self::from(val)
66    }
67}
68
69impl From<u256> for fe256 {
70    fn from(val: u256) -> Self { Self(val) }
71}
72
73impl StrictType for fe256 {
74    const STRICT_LIB_NAME: &'static str = LIB_NAME_FINITE_FIELD;
75    fn strict_name() -> Option<TypeName> { Some(tn!("Fe256")) }
76}
77impl StrictProduct for fe256 {}
78impl StrictTuple for fe256 {
79    const FIELD_COUNT: u8 = 1;
80}
81
82#[cfg(feature = "serde")]
83mod _serde {
84    use serde::de::{Error, Unexpected};
85    use serde::{Deserialize, Deserializer, Serialize, Serializer};
86
87    use super::*;
88
89    impl Serialize for fe256 {
90        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91        where S: Serializer {
92            if serializer.is_human_readable() {
93                self.to_string().serialize(serializer)
94            } else {
95                self.0.serialize(serializer)
96            }
97        }
98    }
99
100    impl<'de> Deserialize<'de> for fe256 {
101        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
102        where D: Deserializer<'de> {
103            if deserializer.is_human_readable() {
104                let s = String::deserialize(deserializer)?;
105                Self::from_str(&s).map_err(|e| D::Error::invalid_value(Unexpected::Str(&s), &e.to_string().as_str()))
106            } else {
107                let val = u256::deserialize(deserializer)?;
108                Ok(Self(val))
109            }
110        }
111    }
112}
113
114#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)]
116pub enum ParseFeError {
117    #[display("field element `{0}` must have a `.fe` suffix.")]
119    NoSuffix(String),
120
121    #[from]
123    #[display(inner)]
124    Value(hex::Error),
125}
126
127impl FromStr for fe256 {
128    type Err = ParseFeError;
129
130    fn from_str(s: &str) -> Result<Self, Self::Err> {
131        let s = s
132            .strip_suffix(".fe")
133            .ok_or_else(|| ParseFeError::NoSuffix(s.to_owned()))?;
134        let bytes = if s.len() % 2 == 1 { TinyBlob::from_hex(&format!("0{s}"))? } else { TinyBlob::from_hex(s)? };
135        const BUF_SIZE: usize = 32;
136        let mut buf = [0u8; BUF_SIZE];
137        if bytes.len() > BUF_SIZE {
138            return Err(hex::Error::InvalidLength(BUF_SIZE, bytes.len()).into());
139        }
140        buf[(BUF_SIZE - bytes.len())..].copy_from_slice(bytes.as_slice());
141        let val = u256::from_be_bytes(buf);
142        Ok(Self(val))
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    #![cfg_attr(coverage_nightly, coverage(off))]
149
150    use amplify::confinement::Confined;
151    use strict_encoding::{StrictDeserialize, StrictDumb, StrictSerialize};
152
153    use super::*;
154
155    #[test]
156    fn display_from_str() {
157        let s = "0000000000000000000000000000000000000000000000000000000000000000.fe";
158        let fe = fe256::from_str(s).unwrap();
159        assert_eq!(fe, fe256::ZERO);
160        assert_eq!(format!("{}", fe), "0.fe");
161        assert_eq!(format!("{:#}", fe), s);
162        assert_eq!(format!("{:?}", fe), "fe256(0x0000000000000000000000000000000000000000000000000000000000000000)");
163
164        let s = "A489C5940DEDEADBEEFBADCAFEFEEDDEEDABCDEF012345678047345495749857.fe";
165        let fe = fe256::from_str(s).unwrap();
166        assert_eq!(format!("{}", fe), s);
167        assert_eq!(format!("{:#}", fe), s);
168        assert_eq!(format!("{:?}", fe), "fe256(0xa489c5940dedeadbeefbadcafefeeddeedabcdef012345678047345495749857)");
169
170        let s = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.fe";
171        let fe = fe256::from_str(s).unwrap();
172        assert_eq!(fe, fe256::from(u256::MAX));
173        assert_eq!(format!("{}", fe), s);
174        assert_eq!(format!("{:#}", fe), s);
175        assert_eq!(format!("{:?}", fe), "fe256(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)");
176
177        let s = "0000000000000000000000000000000000000000000000000000000000000345.fe";
178        let fe = fe256::from_str(s).unwrap();
179        assert_eq!(format!("{}", fe), "345.fe");
180        assert_eq!(format!("{:#}", fe), s);
181        assert_eq!(format!("{:?}", fe), "fe256(0x0000000000000000000000000000000000000000000000000000000000000345)");
182
183        let s = "345.fe";
184        let fe = fe256::from_str(s).unwrap();
185        assert_eq!(format!("{}", fe), "345.fe");
186        assert_eq!(format!("{:#}", fe), "0000000000000000000000000000000000000000000000000000000000000345.fe");
187        assert_eq!(format!("{:?}", fe), "fe256(0x0000000000000000000000000000000000000000000000000000000000000345)");
188
189        let s = "1230000000000000000000000000000000000000000000000000000000000000.fe";
190        let fe = fe256::from_str(s).unwrap();
191        assert_eq!(format!("{}", fe), "1230000000000000000000000000000000000000000000000000000000000000.fe");
192        assert_eq!(format!("{:#}", fe), s);
193        assert_eq!(format!("{:?}", fe), "fe256(0x1230000000000000000000000000000000000000000000000000000000000000)");
194    }
195
196    #[test]
197    #[should_panic(expected = r#"NoSuffix("0000000000000000000000000000000000000000000000000000000000000000")"#)]
198    fn from_str_no_suffix() {
199        let s = "0000000000000000000000000000000000000000000000000000000000000000";
200        fe256::from_str(s).unwrap();
201    }
202
203    #[test]
204    #[should_panic(expected = "Value(InvalidLength(32, 33))")]
205    fn from_str_invalid_len() {
206        let s = "AA0000000000000000000000000000000000000000000000000000000000000000.fe";
207        fe256::from_str(s).unwrap();
208    }
209
210    #[test]
211    fn serde() {
212        use serde_test::{assert_tokens, Configure, Token};
213
214        let s = "A489C5940DEDEADBEEFBADCAFEFEEDDEEDABCDEF012345678047345495749857.fe";
215        let val = fe256::from_str(s).unwrap();
216        let dat = [
217            0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x89, 0xC5, 0x94, 0x0D, 0xED, 0xEA, 0xDB, 0xEE, 0xFB, 0xAD, 0xCA, 0xFE, 0xFE, 0xED, 0xDE, 0xED, 0xAB,
220            0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x80, 0x47, 0x34, 0x54, 0x95, 0x74, 0x98, 0x57,
221        ];
222        assert_eq!(bincode::serialize(&val).unwrap(), dat);
223        assert_eq!(bincode::deserialize::<fe256>(&dat).unwrap(), val);
224        assert_eq!(bincode::serialize(&val).unwrap(), bincode::serialize(&val.0).unwrap());
225        assert_tokens(&val.readable(), &[Token::Str(s)]);
226    }
227
228    #[test]
229    fn from_bytes() {
230        let mut bytes = [
231            0xA4, 0x89, 0xC5, 0x94, 0x0D, 0xED, 0xEA, 0xDB, 0xEE, 0xFB, 0xAD, 0xCA, 0xFE, 0xFE, 0xED, 0xDE, 0xED, 0xAB,
232            0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x80, 0x47, 0x34, 0x54, 0x95, 0x74, 0x98, 0x57,
233        ];
234        bytes.reverse();
236        let fe1 = fe256::from(bytes);
237        let fe2 = fe256::from(Bytes32::from_byte_array(bytes));
238        assert_eq!(fe1, fe2);
239        assert_eq!(fe1.to_string(), "A489C5940DEDEADBEEFBADCAFEFEEDDEEDABCDEF012345678047345495749857.fe");
240    }
241
242    #[test]
243    fn strict_encoding() {
244        #![allow(non_local_definitions)]
245
246        assert_eq!(fe256::strict_dumb(), fe256::ZERO);
247
248        impl StrictSerialize for fe256 {}
249        impl StrictDeserialize for fe256 {}
250
251        let bytes = [
252            0xA4, 0x89, 0xC5, 0x94, 0x0D, 0xED, 0xEA, 0xDB, 0xEE, 0xFB, 0xAD, 0xCA, 0xFE, 0xFE, 0xED, 0xDE, 0xED, 0xAB,
253            0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x80, 0x47, 0x34, 0x54, 0x95, 0x74, 0x98, 0x57,
254        ];
255        let mut rev = bytes;
256        rev.reverse();
258        let fe = fe256::from(rev);
259        assert_eq!(fe.to_strict_serialized::<32>().unwrap().as_slice(), rev.as_slice());
260        assert_eq!(fe, fe256::from_strict_serialized::<32>(Confined::from_iter_checked(rev)).unwrap());
261        assert_eq!(fe.to_string(), "A489C5940DEDEADBEEFBADCAFEFEEDDEEDABCDEF012345678047345495749857.fe");
262    }
263}