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.try_into().map_err(|_unhelpful_err| {
75 Error::Decode(format!("invalid i16 length: {}", bytes.len()))
76 })?;
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.try_into().map_err(|_unhelpful_err| {
121 Error::Decode(format!("invalid i16 length: {}", bytes.len()))
122 })?;
123 Ok(i16::from_be_bytes(arr) as i32)
124 }
125 oid::INT4 => {
126 let arr: [u8; 4] = bytes.try_into().map_err(|_unhelpful_err| {
127 Error::Decode(format!("invalid i32 length: {}", bytes.len()))
128 })?;
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)
145 .map_err(|_unhelpful_err| Error::overflow("i32", "INT2"))?;
146 buf.extend_from_slice(&2_i32.to_be_bytes());
147 buf.extend_from_slice(&v.to_be_bytes());
148 }
149 oid::INT4 => {
150 buf.extend_from_slice(&4_i32.to_be_bytes());
151 buf.extend_from_slice(&self.to_be_bytes());
152 }
153 oid::INT8 => {
154 buf.extend_from_slice(&8_i32.to_be_bytes());
155 buf.extend_from_slice(&(*self as i64).to_be_bytes());
156 }
157 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
158 }
159 Ok(())
160 }
161}
162
163impl FromWireValue<'_> for i64 {
164 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
165 if !matches!(oid, oid::INT2 | oid::INT4 | oid::INT8) {
166 return Err(Error::Decode(format!("cannot decode oid {} as i64", oid)));
167 }
168 let s = simdutf8::compat::from_utf8(bytes)
169 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
170 s.parse()
171 .map_err(|e| Error::Decode(format!("invalid i64: {}", e)))
172 }
173
174 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
175 match oid {
176 oid::INT2 => {
177 let arr: [u8; 2] = bytes.try_into().map_err(|_unhelpful_err| {
178 Error::Decode(format!("invalid i16 length: {}", bytes.len()))
179 })?;
180 Ok(i16::from_be_bytes(arr) as i64)
181 }
182 oid::INT4 => {
183 let arr: [u8; 4] = bytes.try_into().map_err(|_unhelpful_err| {
184 Error::Decode(format!("invalid i32 length: {}", bytes.len()))
185 })?;
186 Ok(i32::from_be_bytes(arr) as i64)
187 }
188 oid::INT8 => {
189 let arr: [u8; 8] = bytes.try_into().map_err(|_unhelpful_err| {
190 Error::Decode(format!("invalid i64 length: {}", bytes.len()))
191 })?;
192 Ok(i64::from_be_bytes(arr))
193 }
194 _ => Err(Error::Decode(format!("cannot decode oid {} as i64", oid))),
195 }
196 }
197}
198
199impl ToWireValue for i64 {
200 fn natural_oid(&self) -> Oid {
201 oid::INT8
202 }
203
204 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
205 match target_oid {
206 oid::INT2 => {
207 let v = i16::try_from(*self)
208 .map_err(|_unhelpful_err| Error::overflow("i64", "INT2"))?;
209 buf.extend_from_slice(&2_i32.to_be_bytes());
210 buf.extend_from_slice(&v.to_be_bytes());
211 }
212 oid::INT4 => {
213 let v = i32::try_from(*self)
214 .map_err(|_unhelpful_err| Error::overflow("i64", "INT4"))?;
215 buf.extend_from_slice(&4_i32.to_be_bytes());
216 buf.extend_from_slice(&v.to_be_bytes());
217 }
218 oid::INT8 => {
219 buf.extend_from_slice(&8_i32.to_be_bytes());
220 buf.extend_from_slice(&self.to_be_bytes());
221 }
222 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
223 }
224 Ok(())
225 }
226}
227
228impl ToWireValue for i8 {
231 fn natural_oid(&self) -> Oid {
232 oid::INT2 }
234
235 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
236 match target_oid {
237 oid::INT2 => {
238 buf.extend_from_slice(&2_i32.to_be_bytes());
239 buf.extend_from_slice(&(*self as i16).to_be_bytes());
240 }
241 oid::INT4 => {
242 buf.extend_from_slice(&4_i32.to_be_bytes());
243 buf.extend_from_slice(&(*self as i32).to_be_bytes());
244 }
245 oid::INT8 => {
246 buf.extend_from_slice(&8_i32.to_be_bytes());
247 buf.extend_from_slice(&(*self as i64).to_be_bytes());
248 }
249 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
250 }
251 Ok(())
252 }
253}
254
255impl ToWireValue for u8 {
258 fn natural_oid(&self) -> Oid {
259 oid::INT2 }
261
262 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
263 match target_oid {
264 oid::INT2 => {
265 buf.extend_from_slice(&2_i32.to_be_bytes());
266 buf.extend_from_slice(&(*self as i16).to_be_bytes());
267 }
268 oid::INT4 => {
269 buf.extend_from_slice(&4_i32.to_be_bytes());
270 buf.extend_from_slice(&(*self as i32).to_be_bytes());
271 }
272 oid::INT8 => {
273 buf.extend_from_slice(&8_i32.to_be_bytes());
274 buf.extend_from_slice(&(*self as i64).to_be_bytes());
275 }
276 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
277 }
278 Ok(())
279 }
280}
281
282impl ToWireValue for u16 {
285 fn natural_oid(&self) -> Oid {
286 oid::INT4
288 }
289
290 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
291 match target_oid {
292 oid::INT2 => {
293 let v = i16::try_from(*self)
294 .map_err(|_unhelpful_err| Error::overflow("u16", "INT2"))?;
295 buf.extend_from_slice(&2_i32.to_be_bytes());
296 buf.extend_from_slice(&v.to_be_bytes());
297 }
298 oid::INT4 => {
299 buf.extend_from_slice(&4_i32.to_be_bytes());
300 buf.extend_from_slice(&(*self as i32).to_be_bytes());
301 }
302 oid::INT8 => {
303 buf.extend_from_slice(&8_i32.to_be_bytes());
304 buf.extend_from_slice(&(*self as i64).to_be_bytes());
305 }
306 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
307 }
308 Ok(())
309 }
310}
311
312impl ToWireValue for u32 {
315 fn natural_oid(&self) -> Oid {
316 oid::INT8
318 }
319
320 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
321 match target_oid {
322 oid::INT2 => {
323 let v = i16::try_from(*self)
324 .map_err(|_unhelpful_err| Error::overflow("u32", "INT2"))?;
325 buf.extend_from_slice(&2_i32.to_be_bytes());
326 buf.extend_from_slice(&v.to_be_bytes());
327 }
328 oid::INT4 => {
329 let v = i32::try_from(*self)
330 .map_err(|_unhelpful_err| Error::overflow("u32", "INT4"))?;
331 buf.extend_from_slice(&4_i32.to_be_bytes());
332 buf.extend_from_slice(&v.to_be_bytes());
333 }
334 oid::INT8 => {
335 buf.extend_from_slice(&8_i32.to_be_bytes());
336 buf.extend_from_slice(&(*self as i64).to_be_bytes());
337 }
338 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
339 }
340 Ok(())
341 }
342}
343
344impl ToWireValue for u64 {
347 fn natural_oid(&self) -> Oid {
348 oid::INT8
349 }
350
351 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
352 match target_oid {
353 oid::INT2 => {
354 let v = i16::try_from(*self)
355 .map_err(|_unhelpful_err| Error::overflow("u64", "INT2"))?;
356 buf.extend_from_slice(&2_i32.to_be_bytes());
357 buf.extend_from_slice(&v.to_be_bytes());
358 }
359 oid::INT4 => {
360 let v = i32::try_from(*self)
361 .map_err(|_unhelpful_err| Error::overflow("u64", "INT4"))?;
362 buf.extend_from_slice(&4_i32.to_be_bytes());
363 buf.extend_from_slice(&v.to_be_bytes());
364 }
365 oid::INT8 => {
366 let v = i64::try_from(*self)
367 .map_err(|_unhelpful_err| Error::overflow("u64", "INT8"))?;
368 buf.extend_from_slice(&8_i32.to_be_bytes());
369 buf.extend_from_slice(&v.to_be_bytes());
370 }
371 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
372 }
373 Ok(())
374 }
375}
376
377impl FromWireValue<'_> for f32 {
380 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
381 if !matches!(oid, oid::FLOAT4 | oid::NUMERIC) {
382 return Err(Error::Decode(format!("cannot decode oid {} as f32", oid)));
383 }
384 let s = simdutf8::compat::from_utf8(bytes)
385 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
386
387 match s {
389 "NaN" => return Ok(f32::NAN),
390 "Infinity" => return Ok(f32::INFINITY),
391 "-Infinity" => return Ok(f32::NEG_INFINITY),
392 _ => {}
393 }
394
395 let value: f64 = s
396 .parse()
397 .map_err(|e| Error::Decode(format!("invalid f32: {}", e)))?;
398
399 if value > f32::MAX as f64 || value < f32::MIN as f64 {
401 return Err(Error::Decode("NUMERIC value overflows f32".to_string()));
402 }
403
404 Ok(value as f32)
405 }
406
407 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
408 match oid {
409 oid::FLOAT4 => {
410 let arr: [u8; 4] = bytes.try_into().map_err(|_unhelpful_err| {
411 Error::Decode(format!("invalid f32 length: {}", bytes.len()))
412 })?;
413 Ok(f32::from_be_bytes(arr))
414 }
415 oid::NUMERIC => numeric_to_f32(bytes),
416 _ => Err(Error::Decode(format!("cannot decode oid {} as f32", oid))),
417 }
418 }
419}
420
421impl ToWireValue for f32 {
422 fn natural_oid(&self) -> Oid {
423 oid::FLOAT4
424 }
425
426 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
427 match target_oid {
428 oid::FLOAT4 => {
429 buf.extend_from_slice(&4_i32.to_be_bytes());
430 buf.extend_from_slice(&self.to_bits().to_be_bytes());
431 }
432 oid::FLOAT8 => {
433 buf.extend_from_slice(&8_i32.to_be_bytes());
434 buf.extend_from_slice(&(*self as f64).to_bits().to_be_bytes());
435 }
436 oid::NUMERIC => {
437 let s = self.to_string();
439 let bytes = s.as_bytes();
440 buf.extend_from_slice(&(bytes.len() as i32).to_be_bytes());
441 buf.extend_from_slice(bytes);
442 }
443 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
444 }
445 Ok(())
446 }
447}
448
449impl FromWireValue<'_> for f64 {
450 fn from_text(oid: Oid, bytes: &[u8]) -> Result<Self> {
451 if !matches!(oid, oid::FLOAT4 | oid::FLOAT8 | oid::NUMERIC) {
452 return Err(Error::Decode(format!("cannot decode oid {} as f64", oid)));
453 }
454 let s = simdutf8::compat::from_utf8(bytes)
455 .map_err(|e| Error::Decode(format!("invalid UTF-8: {}", e)))?;
456
457 match s {
459 "NaN" => return Ok(f64::NAN),
460 "Infinity" => return Ok(f64::INFINITY),
461 "-Infinity" => return Ok(f64::NEG_INFINITY),
462 _ => {}
463 }
464
465 s.parse()
466 .map_err(|e| Error::Decode(format!("invalid f64: {}", e)))
467 }
468
469 fn from_binary(oid: Oid, bytes: &[u8]) -> Result<Self> {
470 match oid {
471 oid::FLOAT4 => {
472 let arr: [u8; 4] = bytes.try_into().map_err(|_unhelpful_err| {
473 Error::Decode(format!("invalid f32 length: {}", bytes.len()))
474 })?;
475 Ok(f32::from_be_bytes(arr) as f64)
476 }
477 oid::FLOAT8 => {
478 let arr: [u8; 8] = bytes.try_into().map_err(|_unhelpful_err| {
479 Error::Decode(format!("invalid f64 length: {}", bytes.len()))
480 })?;
481 Ok(f64::from_be_bytes(arr))
482 }
483 oid::NUMERIC => numeric_to_f64(bytes),
484 _ => Err(Error::Decode(format!("cannot decode oid {} as f64", oid))),
485 }
486 }
487}
488
489impl ToWireValue for f64 {
490 fn natural_oid(&self) -> Oid {
491 oid::FLOAT8
492 }
493
494 fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
495 match target_oid {
496 oid::FLOAT4 => {
497 buf.extend_from_slice(&4_i32.to_be_bytes());
499 buf.extend_from_slice(&(*self as f32).to_bits().to_be_bytes());
500 }
501 oid::FLOAT8 => {
502 buf.extend_from_slice(&8_i32.to_be_bytes());
503 buf.extend_from_slice(&self.to_bits().to_be_bytes());
504 }
505 oid::NUMERIC => {
506 let s = self.to_string();
508 let bytes = s.as_bytes();
509 buf.extend_from_slice(&(bytes.len() as i32).to_be_bytes());
510 buf.extend_from_slice(bytes);
511 }
512 _ => return Err(Error::type_mismatch(self.natural_oid(), target_oid)),
513 }
514 Ok(())
515 }
516}
517
518#[cfg(test)]
519mod tests {
520 use super::*;
521
522 #[test]
523 fn bool_text() {
524 assert!(bool::from_text(oid::BOOL, b"t").unwrap());
525 assert!(bool::from_text(oid::BOOL, b"true").unwrap());
526 assert!(!bool::from_text(oid::BOOL, b"f").unwrap());
527 assert!(!bool::from_text(oid::BOOL, b"false").unwrap());
528 }
529
530 #[test]
531 fn bool_binary() {
532 assert!(bool::from_binary(oid::BOOL, &[1]).unwrap());
533 assert!(!bool::from_binary(oid::BOOL, &[0]).unwrap());
534 }
535
536 #[test]
537 fn i32_text() {
538 assert_eq!(i32::from_text(oid::INT4, b"12345").unwrap(), 12345);
539 assert_eq!(i32::from_text(oid::INT4, b"-12345").unwrap(), -12345);
540 }
541
542 #[test]
543 fn i32_binary() {
544 assert_eq!(
545 i32::from_binary(oid::INT4, &[0, 0, 0x30, 0x39]).unwrap(),
546 12345
547 );
548 }
549
550 #[test]
551 fn f64_text() {
552 assert_eq!(f64::from_text(oid::FLOAT8, b"3.15").unwrap(), 3.15);
553 }
554
555 #[test]
556 fn widening() {
557 assert_eq!(i32::from_binary(oid::INT2, &[0, 42]).unwrap(), 42);
559 assert_eq!(i64::from_binary(oid::INT4, &[0, 0, 0, 42]).unwrap(), 42);
561 let f32_bytes = 3.15_f32.to_be_bytes();
563 assert!((f64::from_binary(oid::FLOAT4, &f32_bytes).unwrap() - 3.15).abs() < 0.001);
564 }
565
566 #[test]
567 fn type_mismatch() {
568 i32::from_text(oid::TEXT, b"123").unwrap_err();
570 }
571
572 #[test]
573 fn i8_encoding() {
574 let mut buf = Vec::new();
575 42i8.encode(oid::INT2, &mut buf).unwrap();
576 assert_eq!(buf.len(), 6);
578 assert_eq!(&buf[0..4], &2_i32.to_be_bytes()); assert_eq!(&buf[4..6], &42_i16.to_be_bytes());
580 }
581
582 #[test]
583 fn u8_encoding() {
584 let mut buf = Vec::new();
585 200u8.encode(oid::INT2, &mut buf).unwrap();
586 assert_eq!(buf.len(), 6);
587 assert_eq!(&buf[0..4], &2_i32.to_be_bytes());
588 assert_eq!(&buf[4..6], &200_i16.to_be_bytes());
589 }
590
591 #[test]
592 fn u16_encoding() {
593 let mut buf = Vec::new();
594 50000u16.encode(oid::INT4, &mut buf).unwrap();
595 assert_eq!(buf.len(), 8);
597 assert_eq!(&buf[0..4], &4_i32.to_be_bytes());
598 assert_eq!(&buf[4..8], &50000_i32.to_be_bytes());
599 }
600
601 #[test]
602 fn u16_overflow_to_int2() {
603 let result = 50000u16.encode(oid::INT2, &mut Vec::new());
605 assert!(result.is_err());
606
607 let mut buf = Vec::new();
609 1000u16.encode(oid::INT2, &mut buf).unwrap();
610 assert_eq!(&buf[4..6], &1000_i16.to_be_bytes());
611 }
612
613 #[test]
614 fn u32_encoding() {
615 let mut buf = Vec::new();
616 3_000_000_000u32.encode(oid::INT8, &mut buf).unwrap();
617 assert_eq!(buf.len(), 12);
619 assert_eq!(&buf[0..4], &8_i32.to_be_bytes());
620 assert_eq!(&buf[4..12], &3_000_000_000_i64.to_be_bytes());
621 }
622
623 #[test]
624 fn u32_overflow_to_int4() {
625 let result = 3_000_000_000u32.encode(oid::INT4, &mut Vec::new());
627 assert!(result.is_err());
628
629 let mut buf = Vec::new();
631 1_000_000u32.encode(oid::INT4, &mut buf).unwrap();
632 assert_eq!(&buf[4..8], &1_000_000_i32.to_be_bytes());
633 }
634
635 #[test]
636 fn u64_encoding() {
637 let mut buf = Vec::new();
638 1000u64.encode(oid::INT8, &mut buf).unwrap();
639 assert_eq!(buf.len(), 12);
640 assert_eq!(&buf[0..4], &8_i32.to_be_bytes());
641 assert_eq!(&buf[4..12], &1000_i64.to_be_bytes());
642 }
643
644 #[test]
645 fn u64_overflow() {
646 let result = u64::MAX.encode(oid::INT8, &mut Vec::new());
648 assert!(result.is_err());
649
650 let mut buf = Vec::new();
652 (i64::MAX as u64).encode(oid::INT8, &mut buf).unwrap();
653 assert_eq!(&buf[4..12], &i64::MAX.to_be_bytes());
654 }
655
656 fn make_numeric(ndigits: i16, weight: i16, sign: u16, dscale: u16, digits: &[i16]) -> Vec<u8> {
658 let mut buf = Vec::new();
659 buf.extend_from_slice(&ndigits.to_be_bytes());
660 buf.extend_from_slice(&weight.to_be_bytes());
661 buf.extend_from_slice(&sign.to_be_bytes());
662 buf.extend_from_slice(&dscale.to_be_bytes());
663 for &d in digits {
664 buf.extend_from_slice(&d.to_be_bytes());
665 }
666 buf
667 }
668
669 #[test]
670 fn numeric_to_f64_basic() {
671 let bytes = make_numeric(2, 0, 0x0000, 2, &[123, 4500]);
673 let result = f64::from_binary(oid::NUMERIC, &bytes).unwrap();
674 assert!((result - 123.45).abs() < 0.001);
675 }
676
677 #[test]
678 fn numeric_to_f64_negative() {
679 let bytes = make_numeric(2, 0, 0x4000, 2, &[123, 4500]);
681 let result = f64::from_binary(oid::NUMERIC, &bytes).unwrap();
682 assert!((result + 123.45).abs() < 0.001);
683 }
684
685 #[test]
686 fn numeric_to_f64_special() {
687 let bytes1 = make_numeric(0, 0, 0xC000, 0, &[]);
689 assert!(f64::from_binary(oid::NUMERIC, &bytes1).unwrap().is_nan());
690
691 let bytes2 = make_numeric(0, 0, 0xD000, 0, &[]);
693 assert_eq!(
694 f64::from_binary(oid::NUMERIC, &bytes2).unwrap(),
695 f64::INFINITY
696 );
697
698 let bytes3 = make_numeric(0, 0, 0xF000, 0, &[]);
700 assert_eq!(
701 f64::from_binary(oid::NUMERIC, &bytes3).unwrap(),
702 f64::NEG_INFINITY
703 );
704 }
705
706 #[test]
707 fn numeric_to_f32_basic() {
708 let bytes = make_numeric(2, 0, 0x0000, 2, &[123, 4500]);
710 let result = f32::from_binary(oid::NUMERIC, &bytes).unwrap();
711 assert!((result - 123.45).abs() < 0.01);
712 }
713
714 #[test]
715 fn numeric_to_f32_special() {
716 let bytes1 = make_numeric(0, 0, 0xC000, 0, &[]);
718 assert!(f32::from_binary(oid::NUMERIC, &bytes1).unwrap().is_nan());
719
720 let bytes2 = make_numeric(0, 0, 0xD000, 0, &[]);
722 assert_eq!(
723 f32::from_binary(oid::NUMERIC, &bytes2).unwrap(),
724 f32::INFINITY
725 );
726
727 let bytes3 = make_numeric(0, 0, 0xF000, 0, &[]);
729 assert_eq!(
730 f32::from_binary(oid::NUMERIC, &bytes3).unwrap(),
731 f32::NEG_INFINITY
732 );
733 }
734
735 #[test]
736 fn f64_from_text_special() {
737 assert!(f64::from_text(oid::NUMERIC, b"NaN").unwrap().is_nan());
738 assert_eq!(
739 f64::from_text(oid::NUMERIC, b"Infinity").unwrap(),
740 f64::INFINITY
741 );
742 assert_eq!(
743 f64::from_text(oid::NUMERIC, b"-Infinity").unwrap(),
744 f64::NEG_INFINITY
745 );
746 }
747
748 #[test]
749 fn f32_from_text_special() {
750 assert!(f32::from_text(oid::NUMERIC, b"NaN").unwrap().is_nan());
751 assert_eq!(
752 f32::from_text(oid::NUMERIC, b"Infinity").unwrap(),
753 f32::INFINITY
754 );
755 assert_eq!(
756 f32::from_text(oid::NUMERIC, b"-Infinity").unwrap(),
757 f32::NEG_INFINITY
758 );
759 }
760}