1use crate::error::{Error, Result};
4use crate::protocol::types::{Oid, oid};
5
6use super::numeric_util::{numeric_to_f32, numeric_to_f64};
7use super::{FromWireValue, ToWireValue};
8
9impl FromWireValue<'_> for bool {
12 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
13 if oid != oid::BOOL {
14 return Err(Error::Decode(format!("cannot decode oid {} as bool", oid)));
15 }
16 match bytes {
17 b"t" | b"true" | b"TRUE" | b"T" | b"1" => Ok(true),
18 b"f" | b"false" | b"FALSE" | b"F" | b"0" => Ok(false),
19 _ => Err(Error::Decode(format!(
20 "invalid boolean: {:?}",
21 String::from_utf8_lossy(bytes)
22 ))),
23 }
24 }
25
26 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
27 if oid != oid::BOOL {
28 return Err(Error::Decode(format!("cannot decode oid {} as bool", oid)));
29 }
30 if bytes.len() != 1 {
31 return Err(Error::Decode(format!(
32 "invalid boolean length: {}",
33 bytes.len()
34 )));
35 }
36 Ok(bytes[0] != 0)
37 }
38}
39
40impl ToWireValue for bool {
41 fn natural_oid(&self) -> Oid {
42 oid::BOOL
43 }
44
45 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
46 match target_oid {
47 oid::BOOL => {
48 buf.extend_from_slice(&1_i32.to_be_bytes());
49 buf.push(if *self { 1 } else { 0 });
50 Ok(())
51 }
52 _ => Err(Error::type_mismatch(self.natural_oid(), target_oid)),
53 }
54 }
55}
56
57impl FromWireValue<'_> for i16 {
60 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
61 if oid != oid::INT2 {
62 return Err(Error::Decode(format!("cannot decode oid {} as i16", oid)));
63 }
64 let s = simdutf8::compat::from_utf8(bytes)
65 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
66 s.parse()
67 .map_err(|e| Error::Decode(format!("invalid i16: {}", e)))
68 }
69
70 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
71 if oid != oid::INT2 {
72 return Err(Error::Decode(format!("cannot decode oid {} as i16", oid)));
73 }
74 let arr: [u8; 2] = bytes
75 .try_into()
76 .map_err(|_| Error::Decode(format!("invalid i16 length: {}", bytes.len())))?;
77 Ok(i16::from_be_bytes(arr))
78 }
79}
80
81impl ToWireValue for i16 {
82 fn natural_oid(&self) -> Oid {
83 oid::INT2
84 }
85
86 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
87 match target_oid {
88 oid::INT2 => {
89 buf.extend_from_slice(&2_i32.to_be_bytes());
90 buf.extend_from_slice(&self.to_be_bytes());
91 }
92 oid::INT4 => {
93 buf.extend_from_slice(&4_i32.to_be_bytes());
94 buf.extend_from_slice(&(*self as i32).to_be_bytes());
95 }
96 oid::INT8 => {
97 buf.extend_from_slice(&8_i32.to_be_bytes());
98 buf.extend_from_slice(&(*self as i64).to_be_bytes());
99 }
100 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
101 }
102 Ok(())
103 }
104}
105
106impl FromWireValue<'_> for i32 {
107 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
108 if !matches!(oid, oid::INT2 | oid::INT4) {
109 return Err(Error::Decode(format!("cannot decode oid {} as i32", oid)));
110 }
111 let s = simdutf8::compat::from_utf8(bytes)
112 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
113 s.parse()
114 .map_err(|e| Error::Decode(format!("invalid i32: {}", e)))
115 }
116
117 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
118 match oid {
119 oid::INT2 => {
120 let arr: [u8; 2] = bytes
121 .try_into()
122 .map_err(|_| Error::Decode(format!("invalid i16 length: {}", bytes.len())))?;
123 Ok(i16::from_be_bytes(arr) as i32)
124 }
125 oid::INT4 => {
126 let arr: [u8; 4] = bytes
127 .try_into()
128 .map_err(|_| Error::Decode(format!("invalid i32 length: {}", bytes.len())))?;
129 Ok(i32::from_be_bytes(arr))
130 }
131 _ => Err(Error::Decode(format!("cannot decode oid {} as i32", oid))),
132 }
133 }
134}
135
136impl ToWireValue for i32 {
137 fn natural_oid(&self) -> Oid {
138 oid::INT4
139 }
140
141 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
142 match target_oid {
143 oid::INT2 => {
144 let v = i16::try_from(*self).map_err(|_| Error::overflow("i32", "INT2"))?;
145 buf.extend_from_slice(&2_i32.to_be_bytes());
146 buf.extend_from_slice(&v.to_be_bytes());
147 }
148 oid::INT4 => {
149 buf.extend_from_slice(&4_i32.to_be_bytes());
150 buf.extend_from_slice(&self.to_be_bytes());
151 }
152 oid::INT8 => {
153 buf.extend_from_slice(&8_i32.to_be_bytes());
154 buf.extend_from_slice(&(*self as i64).to_be_bytes());
155 }
156 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
157 }
158 Ok(())
159 }
160}
161
162impl FromWireValue<'_> for i64 {
163 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
164 if !matches!(oid, oid::INT2 | oid::INT4 | oid::INT8) {
165 return Err(Error::Decode(format!("cannot decode oid {} as i64", oid)));
166 }
167 let s = simdutf8::compat::from_utf8(bytes)
168 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
169 s.parse()
170 .map_err(|e| Error::Decode(format!("invalid i64: {}", e)))
171 }
172
173 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
174 match oid {
175 oid::INT2 => {
176 let arr: [u8; 2] = bytes
177 .try_into()
178 .map_err(|_| Error::Decode(format!("invalid i16 length: {}", bytes.len())))?;
179 Ok(i16::from_be_bytes(arr) as i64)
180 }
181 oid::INT4 => {
182 let arr: [u8; 4] = bytes
183 .try_into()
184 .map_err(|_| Error::Decode(format!("invalid i32 length: {}", bytes.len())))?;
185 Ok(i32::from_be_bytes(arr) as i64)
186 }
187 oid::INT8 => {
188 let arr: [u8; 8] = bytes
189 .try_into()
190 .map_err(|_| Error::Decode(format!("invalid i64 length: {}", bytes.len())))?;
191 Ok(i64::from_be_bytes(arr))
192 }
193 _ => Err(Error::Decode(format!("cannot decode oid {} as i64", oid))),
194 }
195 }
196}
197
198impl ToWireValue for i64 {
199 fn natural_oid(&self) -> Oid {
200 oid::INT8
201 }
202
203 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
204 match target_oid {
205 oid::INT2 => {
206 let v = i16::try_from(*self).map_err(|_| Error::overflow("i64", "INT2"))?;
207 buf.extend_from_slice(&2_i32.to_be_bytes());
208 buf.extend_from_slice(&v.to_be_bytes());
209 }
210 oid::INT4 => {
211 let v = i32::try_from(*self).map_err(|_| Error::overflow("i64", "INT4"))?;
212 buf.extend_from_slice(&4_i32.to_be_bytes());
213 buf.extend_from_slice(&v.to_be_bytes());
214 }
215 oid::INT8 => {
216 buf.extend_from_slice(&8_i32.to_be_bytes());
217 buf.extend_from_slice(&self.to_be_bytes());
218 }
219 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
220 }
221 Ok(())
222 }
223}
224
225impl ToWireValue for i8 {
228 fn natural_oid(&self) -> Oid {
229 oid::INT2 }
231
232 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
233 match target_oid {
234 oid::INT2 => {
235 buf.extend_from_slice(&2_i32.to_be_bytes());
236 buf.extend_from_slice(&(*self as i16).to_be_bytes());
237 }
238 oid::INT4 => {
239 buf.extend_from_slice(&4_i32.to_be_bytes());
240 buf.extend_from_slice(&(*self as i32).to_be_bytes());
241 }
242 oid::INT8 => {
243 buf.extend_from_slice(&8_i32.to_be_bytes());
244 buf.extend_from_slice(&(*self as i64).to_be_bytes());
245 }
246 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
247 }
248 Ok(())
249 }
250}
251
252impl ToWireValue for u8 {
255 fn natural_oid(&self) -> Oid {
256 oid::INT2 }
258
259 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
260 match target_oid {
261 oid::INT2 => {
262 buf.extend_from_slice(&2_i32.to_be_bytes());
263 buf.extend_from_slice(&(*self as i16).to_be_bytes());
264 }
265 oid::INT4 => {
266 buf.extend_from_slice(&4_i32.to_be_bytes());
267 buf.extend_from_slice(&(*self as i32).to_be_bytes());
268 }
269 oid::INT8 => {
270 buf.extend_from_slice(&8_i32.to_be_bytes());
271 buf.extend_from_slice(&(*self as i64).to_be_bytes());
272 }
273 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
274 }
275 Ok(())
276 }
277}
278
279impl ToWireValue for u16 {
282 fn natural_oid(&self) -> Oid {
283 oid::INT4
285 }
286
287 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
288 match target_oid {
289 oid::INT2 => {
290 let v = i16::try_from(*self).map_err(|_| Error::overflow("u16", "INT2"))?;
291 buf.extend_from_slice(&2_i32.to_be_bytes());
292 buf.extend_from_slice(&v.to_be_bytes());
293 }
294 oid::INT4 => {
295 buf.extend_from_slice(&4_i32.to_be_bytes());
296 buf.extend_from_slice(&(*self as i32).to_be_bytes());
297 }
298 oid::INT8 => {
299 buf.extend_from_slice(&8_i32.to_be_bytes());
300 buf.extend_from_slice(&(*self as i64).to_be_bytes());
301 }
302 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
303 }
304 Ok(())
305 }
306}
307
308impl ToWireValue for u32 {
311 fn natural_oid(&self) -> Oid {
312 oid::INT8
314 }
315
316 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
317 match target_oid {
318 oid::INT2 => {
319 let v = i16::try_from(*self).map_err(|_| Error::overflow("u32", "INT2"))?;
320 buf.extend_from_slice(&2_i32.to_be_bytes());
321 buf.extend_from_slice(&v.to_be_bytes());
322 }
323 oid::INT4 => {
324 let v = i32::try_from(*self).map_err(|_| Error::overflow("u32", "INT4"))?;
325 buf.extend_from_slice(&4_i32.to_be_bytes());
326 buf.extend_from_slice(&v.to_be_bytes());
327 }
328 oid::INT8 => {
329 buf.extend_from_slice(&8_i32.to_be_bytes());
330 buf.extend_from_slice(&(*self as i64).to_be_bytes());
331 }
332 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
333 }
334 Ok(())
335 }
336}
337
338impl ToWireValue for u64 {
341 fn natural_oid(&self) -> Oid {
342 oid::INT8
343 }
344
345 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
346 match target_oid {
347 oid::INT2 => {
348 let v = i16::try_from(*self).map_err(|_| Error::overflow("u64", "INT2"))?;
349 buf.extend_from_slice(&2_i32.to_be_bytes());
350 buf.extend_from_slice(&v.to_be_bytes());
351 }
352 oid::INT4 => {
353 let v = i32::try_from(*self).map_err(|_| Error::overflow("u64", "INT4"))?;
354 buf.extend_from_slice(&4_i32.to_be_bytes());
355 buf.extend_from_slice(&v.to_be_bytes());
356 }
357 oid::INT8 => {
358 let v = i64::try_from(*self).map_err(|_| Error::overflow("u64", "INT8"))?;
359 buf.extend_from_slice(&8_i32.to_be_bytes());
360 buf.extend_from_slice(&v.to_be_bytes());
361 }
362 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
363 }
364 Ok(())
365 }
366}
367
368impl FromWireValue<'_> for f32 {
371 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
372 if !matches!(oid, oid::FLOAT4 | oid::NUMERIC) {
373 return Err(Error::Decode(format!("cannot decode oid {} as f32", oid)));
374 }
375 let s = simdutf8::compat::from_utf8(bytes)
376 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
377
378 match s {
380 "NaN" => return Ok(f32::NAN),
381 "Infinity" => return Ok(f32::INFINITY),
382 "-Infinity" => return Ok(f32::NEG_INFINITY),
383 _ => {}
384 }
385
386 let value: f64 = s
387 .parse()
388 .map_err(|e| Error::Decode(format!("invalid f32: {}", e)))?;
389
390 if value > f32::MAX as f64 || value < f32::MIN as f64 {
392 return Err(Error::Decode("NUMERIC value overflows f32".to_string()));
393 }
394
395 Ok(value as f32)
396 }
397
398 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
399 match oid {
400 oid::FLOAT4 => {
401 let arr: [u8; 4] = bytes
402 .try_into()
403 .map_err(|_| Error::Decode(format!("invalid f32 length: {}", bytes.len())))?;
404 Ok(f32::from_be_bytes(arr))
405 }
406 oid::NUMERIC => numeric_to_f32(bytes),
407 _ => Err(Error::Decode(format!("cannot decode oid {} as f32", oid))),
408 }
409 }
410}
411
412impl ToWireValue for f32 {
413 fn natural_oid(&self) -> Oid {
414 oid::FLOAT4
415 }
416
417 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
418 match target_oid {
419 oid::FLOAT4 => {
420 buf.extend_from_slice(&4_i32.to_be_bytes());
421 buf.extend_from_slice(&self.to_bits().to_be_bytes());
422 }
423 oid::FLOAT8 => {
424 buf.extend_from_slice(&8_i32.to_be_bytes());
425 buf.extend_from_slice(&(*self as f64).to_bits().to_be_bytes());
426 }
427 oid::NUMERIC => {
428 let s = self.to_string();
430 let bytes = s.as_bytes();
431 buf.extend_from_slice(&(bytes.len() as i32).to_be_bytes());
432 buf.extend_from_slice(bytes);
433 }
434 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
435 }
436 Ok(())
437 }
438}
439
440impl FromWireValue<'_> for f64 {
441 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
442 if !matches!(oid, oid::FLOAT4 | oid::FLOAT8 | oid::NUMERIC) {
443 return Err(Error::Decode(format!("cannot decode oid {} as f64", oid)));
444 }
445 let s = simdutf8::compat::from_utf8(bytes)
446 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
447
448 match s {
450 "NaN" => return Ok(f64::NAN),
451 "Infinity" => return Ok(f64::INFINITY),
452 "-Infinity" => return Ok(f64::NEG_INFINITY),
453 _ => {}
454 }
455
456 s.parse()
457 .map_err(|e| Error::Decode(format!("invalid f64: {}", e)))
458 }
459
460 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
461 match oid {
462 oid::FLOAT4 => {
463 let arr: [u8; 4] = bytes
464 .try_into()
465 .map_err(|_| Error::Decode(format!("invalid f32 length: {}", bytes.len())))?;
466 Ok(f32::from_be_bytes(arr) as f64)
467 }
468 oid::FLOAT8 => {
469 let arr: [u8; 8] = bytes
470 .try_into()
471 .map_err(|_| Error::Decode(format!("invalid f64 length: {}", bytes.len())))?;
472 Ok(f64::from_be_bytes(arr))
473 }
474 oid::NUMERIC => numeric_to_f64(bytes),
475 _ => Err(Error::Decode(format!("cannot decode oid {} as f64", oid))),
476 }
477 }
478}
479
480impl ToWireValue for f64 {
481 fn natural_oid(&self) -> Oid {
482 oid::FLOAT8
483 }
484
485 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
486 match target_oid {
487 oid::FLOAT4 => {
488 buf.extend_from_slice(&4_i32.to_be_bytes());
490 buf.extend_from_slice(&(*self as f32).to_bits().to_be_bytes());
491 }
492 oid::FLOAT8 => {
493 buf.extend_from_slice(&8_i32.to_be_bytes());
494 buf.extend_from_slice(&self.to_bits().to_be_bytes());
495 }
496 oid::NUMERIC => {
497 let s = self.to_string();
499 let bytes = s.as_bytes();
500 buf.extend_from_slice(&(bytes.len() as i32).to_be_bytes());
501 buf.extend_from_slice(bytes);
502 }
503 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
504 }
505 Ok(())
506 }
507}
508
509#[cfg(test)]
510mod tests {
511 use super::*;
512
513 #[test]
514 fn test_bool_text() {
515 assert!(bool::from_text(oid::BOOL, b"t").unwrap());
516 assert!(bool::from_text(oid::BOOL, b"true").unwrap());
517 assert!(!bool::from_text(oid::BOOL, b"f").unwrap());
518 assert!(!bool::from_text(oid::BOOL, b"false").unwrap());
519 }
520
521 #[test]
522 fn test_bool_binary() {
523 assert!(bool::from_binary(oid::BOOL, &[1]).unwrap());
524 assert!(!bool::from_binary(oid::BOOL, &[0]).unwrap());
525 }
526
527 #[test]
528 fn test_i32_text() {
529 assert_eq!(i32::from_text(oid::INT4, b"12345").unwrap(), 12345);
530 assert_eq!(i32::from_text(oid::INT4, b"-12345").unwrap(), -12345);
531 }
532
533 #[test]
534 fn test_i32_binary() {
535 assert_eq!(
536 i32::from_binary(oid::INT4, &[0, 0, 0x30, 0x39]).unwrap(),
537 12345
538 );
539 }
540
541 #[test]
542 fn test_f64_text() {
543 assert_eq!(f64::from_text(oid::FLOAT8, b"3.14").unwrap(), 3.14);
544 }
545
546 #[test]
547 fn test_widening() {
548 assert_eq!(i32::from_binary(oid::INT2, &[0, 42]).unwrap(), 42);
550 assert_eq!(i64::from_binary(oid::INT4, &[0, 0, 0, 42]).unwrap(), 42);
552 let f32_bytes = 3.14_f32.to_be_bytes();
554 assert!((f64::from_binary(oid::FLOAT4, &f32_bytes).unwrap() - 3.14).abs() < 0.001);
555 }
556
557 #[test]
558 fn test_type_mismatch() {
559 assert!(i32::from_text(oid::TEXT, b"123").is_err());
561 }
562
563 #[test]
564 fn test_i8_encoding() {
565 let mut buf = Vec::new();
566 42i8.encode(oid::INT2, &mut buf).unwrap();
567 assert_eq!(buf.len(), 6);
569 assert_eq!(&buf[0..4], &2_i32.to_be_bytes()); assert_eq!(&buf[4..6], &42_i16.to_be_bytes());
571 }
572
573 #[test]
574 fn test_u8_encoding() {
575 let mut buf = Vec::new();
576 200u8.encode(oid::INT2, &mut buf).unwrap();
577 assert_eq!(buf.len(), 6);
578 assert_eq!(&buf[0..4], &2_i32.to_be_bytes());
579 assert_eq!(&buf[4..6], &200_i16.to_be_bytes());
580 }
581
582 #[test]
583 fn test_u16_encoding() {
584 let mut buf = Vec::new();
585 50000u16.encode(oid::INT4, &mut buf).unwrap();
586 assert_eq!(buf.len(), 8);
588 assert_eq!(&buf[0..4], &4_i32.to_be_bytes());
589 assert_eq!(&buf[4..8], &50000_i32.to_be_bytes());
590 }
591
592 #[test]
593 fn test_u16_overflow_to_int2() {
594 let result = 50000u16.encode(oid::INT2, &mut Vec::new());
596 assert!(result.is_err());
597
598 let mut buf = Vec::new();
600 1000u16.encode(oid::INT2, &mut buf).unwrap();
601 assert_eq!(&buf[4..6], &1000_i16.to_be_bytes());
602 }
603
604 #[test]
605 fn test_u32_encoding() {
606 let mut buf = Vec::new();
607 3_000_000_000u32.encode(oid::INT8, &mut buf).unwrap();
608 assert_eq!(buf.len(), 12);
610 assert_eq!(&buf[0..4], &8_i32.to_be_bytes());
611 assert_eq!(&buf[4..12], &3_000_000_000_i64.to_be_bytes());
612 }
613
614 #[test]
615 fn test_u32_overflow_to_int4() {
616 let result = 3_000_000_000u32.encode(oid::INT4, &mut Vec::new());
618 assert!(result.is_err());
619
620 let mut buf = Vec::new();
622 1_000_000u32.encode(oid::INT4, &mut buf).unwrap();
623 assert_eq!(&buf[4..8], &1_000_000_i32.to_be_bytes());
624 }
625
626 #[test]
627 fn test_u64_encoding() {
628 let mut buf = Vec::new();
629 1000u64.encode(oid::INT8, &mut buf).unwrap();
630 assert_eq!(buf.len(), 12);
631 assert_eq!(&buf[0..4], &8_i32.to_be_bytes());
632 assert_eq!(&buf[4..12], &1000_i64.to_be_bytes());
633 }
634
635 #[test]
636 fn test_u64_overflow() {
637 let result = u64::MAX.encode(oid::INT8, &mut Vec::new());
639 assert!(result.is_err());
640
641 let mut buf = Vec::new();
643 (i64::MAX as u64).encode(oid::INT8, &mut buf).unwrap();
644 assert_eq!(&buf[4..12], &i64::MAX.to_be_bytes());
645 }
646
647 fn make_numeric(ndigits: i16, weight: i16, sign: u16, dscale: u16, digits: &[i16]) -> Vec<u8> {
649 let mut buf = Vec::new();
650 buf.extend_from_slice(&ndigits.to_be_bytes());
651 buf.extend_from_slice(&weight.to_be_bytes());
652 buf.extend_from_slice(&sign.to_be_bytes());
653 buf.extend_from_slice(&dscale.to_be_bytes());
654 for &d in digits {
655 buf.extend_from_slice(&d.to_be_bytes());
656 }
657 buf
658 }
659
660 #[test]
661 fn test_numeric_to_f64() {
662 let bytes = make_numeric(2, 0, 0x0000, 2, &[123, 4500]);
664 let result = f64::from_binary(oid::NUMERIC, &bytes).unwrap();
665 assert!((result - 123.45).abs() < 0.001);
666 }
667
668 #[test]
669 fn test_numeric_to_f64_negative() {
670 let bytes = make_numeric(2, 0, 0x4000, 2, &[123, 4500]);
672 let result = f64::from_binary(oid::NUMERIC, &bytes).unwrap();
673 assert!((result + 123.45).abs() < 0.001);
674 }
675
676 #[test]
677 fn test_numeric_to_f64_special() {
678 let bytes = make_numeric(0, 0, 0xC000, 0, &[]);
680 assert!(f64::from_binary(oid::NUMERIC, &bytes).unwrap().is_nan());
681
682 let bytes = make_numeric(0, 0, 0xD000, 0, &[]);
684 assert_eq!(
685 f64::from_binary(oid::NUMERIC, &bytes).unwrap(),
686 f64::INFINITY
687 );
688
689 let bytes = make_numeric(0, 0, 0xF000, 0, &[]);
691 assert_eq!(
692 f64::from_binary(oid::NUMERIC, &bytes).unwrap(),
693 f64::NEG_INFINITY
694 );
695 }
696
697 #[test]
698 fn test_numeric_to_f32() {
699 let bytes = make_numeric(2, 0, 0x0000, 2, &[123, 4500]);
701 let result = f32::from_binary(oid::NUMERIC, &bytes).unwrap();
702 assert!((result - 123.45).abs() < 0.01);
703 }
704
705 #[test]
706 fn test_numeric_to_f32_special() {
707 let bytes = make_numeric(0, 0, 0xC000, 0, &[]);
709 assert!(f32::from_binary(oid::NUMERIC, &bytes).unwrap().is_nan());
710
711 let bytes = make_numeric(0, 0, 0xD000, 0, &[]);
713 assert_eq!(
714 f32::from_binary(oid::NUMERIC, &bytes).unwrap(),
715 f32::INFINITY
716 );
717
718 let bytes = make_numeric(0, 0, 0xF000, 0, &[]);
720 assert_eq!(
721 f32::from_binary(oid::NUMERIC, &bytes).unwrap(),
722 f32::NEG_INFINITY
723 );
724 }
725
726 #[test]
727 fn test_f64_from_text_special() {
728 assert!(f64::from_text(oid::NUMERIC, b"NaN").unwrap().is_nan());
729 assert_eq!(
730 f64::from_text(oid::NUMERIC, b"Infinity").unwrap(),
731 f64::INFINITY
732 );
733 assert_eq!(
734 f64::from_text(oid::NUMERIC, b"-Infinity").unwrap(),
735 f64::NEG_INFINITY
736 );
737 }
738
739 #[test]
740 fn test_f32_from_text_special() {
741 assert!(f32::from_text(oid::NUMERIC, b"NaN").unwrap().is_nan());
742 assert_eq!(
743 f32::from_text(oid::NUMERIC, b"Infinity").unwrap(),
744 f32::INFINITY
745 );
746 assert_eq!(
747 f32::from_text(oid::NUMERIC, b"-Infinity").unwrap(),
748 f32::NEG_INFINITY
749 );
750 }
751}