1use super::error::BinaryError;
4use lnmp_core::LnmpValue;
5
6#[repr(u8)]
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum TypeTag {
10 Int = 0x01,
12 Float = 0x02,
14 Bool = 0x03,
16 String = 0x04,
18 StringArray = 0x05,
20 NestedRecord = 0x06,
22 NestedArray = 0x07,
24 Embedding = 0x08,
26 Reserved09 = 0x09,
28 QuantizedEmbedding = 0x0A,
30 IntArray = 0x0B,
32 FloatArray = 0x0C,
34 BoolArray = 0x0D,
36 Reserved0E = 0x0E,
38 Reserved0F = 0x0F,
40}
41
42impl TypeTag {
43 pub fn from_u8(byte: u8) -> Result<Self, BinaryError> {
45 match byte {
46 0x01 => Ok(TypeTag::Int),
47 0x02 => Ok(TypeTag::Float),
48 0x03 => Ok(TypeTag::Bool),
49 0x04 => Ok(TypeTag::String),
50 0x05 => Ok(TypeTag::StringArray),
51 0x06 => Ok(TypeTag::NestedRecord),
52 0x07 => Ok(TypeTag::NestedArray),
53 0x08 => Ok(TypeTag::Embedding),
54 0x09 => Ok(TypeTag::Reserved09),
55 0x0A => Ok(TypeTag::QuantizedEmbedding),
56 0x0B => Ok(TypeTag::IntArray),
57 0x0C => Ok(TypeTag::FloatArray),
58 0x0D => Ok(TypeTag::BoolArray),
59 0x0E => Ok(TypeTag::Reserved0E),
60 0x0F => Ok(TypeTag::Reserved0F),
61 _ => Err(BinaryError::InvalidTypeTag { tag: byte }),
62 }
63 }
64
65 pub fn to_u8(self) -> u8 {
67 self as u8
68 }
69
70 pub fn is_v0_5_type(&self) -> bool {
72 matches!(
73 self,
74 TypeTag::NestedRecord
75 | TypeTag::NestedArray
76 | TypeTag::Embedding
77 | TypeTag::QuantizedEmbedding
78 | TypeTag::Reserved09
79 | TypeTag::IntArray
80 | TypeTag::FloatArray
81 | TypeTag::BoolArray
82 | TypeTag::Reserved0E
83 | TypeTag::Reserved0F
84 )
85 }
86
87 pub fn is_reserved(&self) -> bool {
89 matches!(
90 self,
91 TypeTag::Reserved09 | TypeTag::Reserved0E | TypeTag::Reserved0F
92 )
93 }
94}
95
96#[derive(Debug, Clone, PartialEq)]
98pub enum BinaryValue {
99 Int(i64),
101 Float(f64),
103 Bool(bool),
105 String(String),
107 StringArray(Vec<String>),
109 IntArray(Vec<i64>),
111 FloatArray(Vec<f64>),
113 BoolArray(Vec<bool>),
115 NestedRecord(Box<lnmp_core::LnmpRecord>),
117 NestedArray(Vec<lnmp_core::LnmpRecord>),
119 Embedding(lnmp_embedding::Vector),
121 QuantizedEmbedding(lnmp_quant::QuantizedVector),
123}
124
125impl BinaryValue {
126 pub fn from_lnmp_value(value: &LnmpValue) -> Result<Self, BinaryError> {
130 match value {
131 LnmpValue::Int(i) => Ok(BinaryValue::Int(*i)),
132 LnmpValue::Float(f) => Ok(BinaryValue::Float(*f)),
133 LnmpValue::Bool(b) => Ok(BinaryValue::Bool(*b)),
134 LnmpValue::String(s) => Ok(BinaryValue::String(s.clone())),
135 LnmpValue::StringArray(arr) => Ok(BinaryValue::StringArray(arr.clone())),
136 LnmpValue::IntArray(arr) => Ok(BinaryValue::IntArray(arr.clone())),
137 LnmpValue::FloatArray(arr) => Ok(BinaryValue::FloatArray(arr.clone())),
138 LnmpValue::BoolArray(arr) => Ok(BinaryValue::BoolArray(arr.clone())),
139 LnmpValue::NestedRecord(rec) => Ok(BinaryValue::NestedRecord(rec.clone())),
140 LnmpValue::NestedArray(arr) => Ok(BinaryValue::NestedArray(arr.clone())),
141 LnmpValue::Embedding(vec) => Ok(BinaryValue::Embedding(vec.clone())),
142 LnmpValue::EmbeddingDelta(_) => Err(BinaryError::InvalidValue {
143 reason: "EmbeddingDelta cannot be encoded as BinaryValue, use full embedding"
144 .into(),
145 field_id: 0,
146 type_tag: 0x08,
147 }),
148 LnmpValue::QuantizedEmbedding(qv) => Ok(BinaryValue::QuantizedEmbedding(qv.clone())),
149 }
150 }
151
152 pub fn from_lnmp_value_v0_4(value: &LnmpValue) -> Result<Self, BinaryError> {
156 match value {
157 LnmpValue::Int(i) => Ok(BinaryValue::Int(*i)),
158 LnmpValue::Float(f) => Ok(BinaryValue::Float(*f)),
159 LnmpValue::Bool(b) => Ok(BinaryValue::Bool(*b)),
160 LnmpValue::String(s) => Ok(BinaryValue::String(s.clone())),
161 LnmpValue::StringArray(arr) => Ok(BinaryValue::StringArray(arr.clone())),
162 LnmpValue::IntArray(_) => Err(BinaryError::InvalidValue {
163 field_id: 0,
164 type_tag: 0x0B,
165 reason: "IntArray not supported in v0.4 binary format".to_string(),
166 }),
167 LnmpValue::FloatArray(_) => Err(BinaryError::InvalidValue {
168 field_id: 0,
169 type_tag: 0x0C,
170 reason: "FloatArray not supported in v0.4 binary format".to_string(),
171 }),
172 LnmpValue::BoolArray(_) => Err(BinaryError::InvalidValue {
173 field_id: 0,
174 type_tag: 0x0D,
175 reason: "BoolArray not supported in v0.4 binary format".to_string(),
176 }),
177 LnmpValue::NestedRecord(_) => Err(BinaryError::InvalidValue {
178 field_id: 0,
179 type_tag: 0x06,
180 reason: "Nested records not supported in v0.4 binary format".to_string(),
181 }),
182 LnmpValue::NestedArray(_) => Err(BinaryError::InvalidValue {
183 field_id: 0,
184 type_tag: 0x07,
185 reason: "Nested arrays not supported in v0.4 binary format".to_string(),
186 }),
187 LnmpValue::Embedding(_) => Err(BinaryError::InvalidValue {
188 field_id: 0,
189 type_tag: 0x08,
190 reason: "Embeddings not supported in v0.4 binary format".to_string(),
191 }),
192 LnmpValue::EmbeddingDelta(_) => Err(BinaryError::InvalidValue {
193 reason: "EmbeddingDelta not supported in v0.4".to_string(),
194 field_id: 0,
195 type_tag: 0x08,
196 }),
197 LnmpValue::QuantizedEmbedding(_) => Err(BinaryError::InvalidValue {
198 reason: "QuantizedEmbedding not supported in v0.4".to_string(),
199 field_id: 0,
200 type_tag: 0x0A,
201 }),
202 }
203 }
204
205 pub fn to_lnmp_value(&self) -> LnmpValue {
207 match self {
208 BinaryValue::Int(i) => LnmpValue::Int(*i),
209 BinaryValue::Float(f) => LnmpValue::Float(*f),
210 BinaryValue::Bool(b) => LnmpValue::Bool(*b),
211 BinaryValue::String(s) => LnmpValue::String(s.clone()),
212 BinaryValue::StringArray(arr) => LnmpValue::StringArray(arr.clone()),
213 BinaryValue::IntArray(arr) => LnmpValue::IntArray(arr.clone()),
214 BinaryValue::FloatArray(arr) => LnmpValue::FloatArray(arr.clone()),
215 BinaryValue::BoolArray(arr) => LnmpValue::BoolArray(arr.clone()),
216 BinaryValue::NestedRecord(rec) => LnmpValue::NestedRecord(rec.clone()),
217 BinaryValue::NestedArray(arr) => LnmpValue::NestedArray(arr.clone()),
218 BinaryValue::Embedding(vec) => LnmpValue::Embedding(vec.clone()),
219 BinaryValue::QuantizedEmbedding(qv) => LnmpValue::QuantizedEmbedding(qv.clone()),
220 }
221 }
222
223 pub fn type_tag(&self) -> TypeTag {
225 match self {
226 BinaryValue::Int(_) => TypeTag::Int,
227 BinaryValue::Float(_) => TypeTag::Float,
228 BinaryValue::Bool(_) => TypeTag::Bool,
229 BinaryValue::String(_) => TypeTag::String,
230 BinaryValue::StringArray(_) => TypeTag::StringArray,
231 BinaryValue::IntArray(_) => TypeTag::IntArray,
232 BinaryValue::FloatArray(_) => TypeTag::FloatArray,
233 BinaryValue::BoolArray(_) => TypeTag::BoolArray,
234 BinaryValue::NestedRecord(_) => TypeTag::NestedRecord,
235 BinaryValue::NestedArray(_) => TypeTag::NestedArray,
236 BinaryValue::Embedding(_) => TypeTag::Embedding,
237 BinaryValue::QuantizedEmbedding(_) => TypeTag::QuantizedEmbedding,
238 }
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 #![allow(clippy::approx_constant)]
245
246 use super::*;
247 use lnmp_core::LnmpRecord;
248
249 #[test]
250 fn test_type_tag_from_u8() {
251 assert_eq!(TypeTag::from_u8(0x01).unwrap(), TypeTag::Int);
252 assert_eq!(TypeTag::from_u8(0x02).unwrap(), TypeTag::Float);
253 assert_eq!(TypeTag::from_u8(0x03).unwrap(), TypeTag::Bool);
254 assert_eq!(TypeTag::from_u8(0x04).unwrap(), TypeTag::String);
255 assert_eq!(TypeTag::from_u8(0x05).unwrap(), TypeTag::StringArray);
256 }
257
258 #[test]
259 fn test_type_tag_from_u8_invalid() {
260 assert!(TypeTag::from_u8(0x00).is_err());
261 assert!(TypeTag::from_u8(0xFF).is_err());
262 }
263
264 #[test]
265 fn test_type_tag_from_u8_v0_5_types() {
266 assert_eq!(TypeTag::from_u8(0x06).unwrap(), TypeTag::NestedRecord);
268 assert_eq!(TypeTag::from_u8(0x07).unwrap(), TypeTag::NestedArray);
269 }
270
271 #[test]
272 fn test_type_tag_from_u8_reserved() {
273 assert_eq!(TypeTag::from_u8(0x08).unwrap(), TypeTag::Embedding);
275 assert_eq!(TypeTag::from_u8(0x09).unwrap(), TypeTag::Reserved09);
276 assert_eq!(TypeTag::from_u8(0x0A).unwrap(), TypeTag::QuantizedEmbedding);
277 assert_eq!(TypeTag::from_u8(0x0B).unwrap(), TypeTag::IntArray);
278 assert_eq!(TypeTag::from_u8(0x0C).unwrap(), TypeTag::FloatArray);
279 assert_eq!(TypeTag::from_u8(0x0D).unwrap(), TypeTag::BoolArray);
280 assert_eq!(TypeTag::from_u8(0x0E).unwrap(), TypeTag::Reserved0E);
281 assert_eq!(TypeTag::from_u8(0x0F).unwrap(), TypeTag::Reserved0F);
282 }
283
284 #[test]
285 fn test_type_tag_to_u8() {
286 assert_eq!(TypeTag::Int.to_u8(), 0x01);
287 assert_eq!(TypeTag::Float.to_u8(), 0x02);
288 assert_eq!(TypeTag::Bool.to_u8(), 0x03);
289 assert_eq!(TypeTag::String.to_u8(), 0x04);
290 assert_eq!(TypeTag::StringArray.to_u8(), 0x05);
291 }
292
293 #[test]
294 fn test_type_tag_round_trip() {
295 let tags = vec![
296 TypeTag::Int,
297 TypeTag::Float,
298 TypeTag::Bool,
299 TypeTag::String,
300 TypeTag::StringArray,
301 TypeTag::NestedRecord,
302 TypeTag::NestedArray,
303 TypeTag::Embedding,
304 TypeTag::Reserved09,
305 TypeTag::QuantizedEmbedding,
306 TypeTag::IntArray,
307 TypeTag::FloatArray,
308 TypeTag::BoolArray,
309 TypeTag::Reserved0E,
310 TypeTag::Reserved0F,
311 ];
312
313 for tag in tags {
314 let byte = tag.to_u8();
315 let parsed = TypeTag::from_u8(byte).unwrap();
316 assert_eq!(parsed, tag);
317 }
318 }
319
320 #[test]
321 fn test_type_tag_is_v0_5_type() {
322 assert!(!TypeTag::Int.is_v0_5_type());
324 assert!(!TypeTag::Float.is_v0_5_type());
325 assert!(!TypeTag::Bool.is_v0_5_type());
326 assert!(!TypeTag::String.is_v0_5_type());
327 assert!(!TypeTag::StringArray.is_v0_5_type());
328
329 assert!(TypeTag::NestedRecord.is_v0_5_type());
331 assert!(TypeTag::NestedArray.is_v0_5_type());
332 assert!(TypeTag::Embedding.is_v0_5_type());
333 assert!(TypeTag::Reserved09.is_v0_5_type());
334 assert!(TypeTag::QuantizedEmbedding.is_v0_5_type());
335 assert!(TypeTag::IntArray.is_v0_5_type());
336 assert!(TypeTag::FloatArray.is_v0_5_type());
337 assert!(TypeTag::BoolArray.is_v0_5_type());
338 assert!(TypeTag::Reserved0E.is_v0_5_type());
339 assert!(TypeTag::Reserved0F.is_v0_5_type());
340 }
341
342 #[test]
343 fn test_type_tag_is_reserved() {
344 assert!(!TypeTag::Int.is_reserved());
346 assert!(!TypeTag::Float.is_reserved());
347 assert!(!TypeTag::Bool.is_reserved());
348 assert!(!TypeTag::String.is_reserved());
349 assert!(!TypeTag::StringArray.is_reserved());
350 assert!(!TypeTag::NestedRecord.is_reserved());
351 assert!(!TypeTag::NestedArray.is_reserved());
352
353 assert!(!TypeTag::Embedding.is_reserved());
355 assert!(TypeTag::Reserved09.is_reserved());
356 assert!(!TypeTag::QuantizedEmbedding.is_reserved());
357 assert!(!TypeTag::IntArray.is_reserved());
358 assert!(!TypeTag::FloatArray.is_reserved());
359 assert!(!TypeTag::BoolArray.is_reserved());
360 assert!(TypeTag::Reserved0E.is_reserved());
361 assert!(TypeTag::Reserved0F.is_reserved());
362 }
363
364 #[test]
365 fn test_binary_value_from_lnmp_int() {
366 let lnmp_val = LnmpValue::Int(42);
367 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
368 assert_eq!(binary_val, BinaryValue::Int(42));
369 }
370
371 #[test]
372 fn test_binary_value_from_lnmp_float() {
373 let lnmp_val = LnmpValue::Float(3.14);
374 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
375 assert_eq!(binary_val, BinaryValue::Float(3.14));
376 }
377
378 #[test]
379 fn test_binary_value_from_lnmp_bool() {
380 let lnmp_val = LnmpValue::Bool(true);
381 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
382 assert_eq!(binary_val, BinaryValue::Bool(true));
383 }
384
385 #[test]
386 fn test_binary_value_from_lnmp_string() {
387 let lnmp_val = LnmpValue::String("hello".to_string());
388 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
389 assert_eq!(binary_val, BinaryValue::String("hello".to_string()));
390 }
391
392 #[test]
393 fn test_binary_value_from_lnmp_string_array() {
394 let lnmp_val = LnmpValue::StringArray(vec!["a".to_string(), "b".to_string()]);
395 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
396 assert_eq!(
397 binary_val,
398 BinaryValue::StringArray(vec!["a".to_string(), "b".to_string()])
399 );
400 }
401
402 #[test]
403 fn test_binary_value_from_lnmp_nested_record() {
404 let nested = LnmpValue::NestedRecord(Box::new(LnmpRecord::new()));
406 let result = BinaryValue::from_lnmp_value(&nested);
407 assert!(result.is_ok());
408 match result.unwrap() {
409 BinaryValue::NestedRecord(_) => {}
410 _ => panic!("Expected NestedRecord variant"),
411 }
412 }
413
414 #[test]
415 fn test_binary_value_from_lnmp_nested_array() {
416 let nested = LnmpValue::NestedArray(vec![]);
418 let result = BinaryValue::from_lnmp_value(&nested);
419 assert!(result.is_ok());
420 match result.unwrap() {
421 BinaryValue::NestedArray(_) => {}
422 _ => panic!("Expected NestedArray variant"),
423 }
424 }
425
426 #[test]
427 fn test_binary_value_from_lnmp_nested_record_error_v0_4() {
428 let nested = LnmpValue::NestedRecord(Box::new(LnmpRecord::new()));
430 let result = BinaryValue::from_lnmp_value_v0_4(&nested);
431 assert!(result.is_err());
432 match result {
433 Err(BinaryError::InvalidValue { reason, .. }) => {
434 assert!(reason.contains("not supported in v0.4"));
435 }
436 _ => panic!("Expected InvalidValue error"),
437 }
438 }
439
440 #[test]
441 fn test_binary_value_from_lnmp_nested_array_error_v0_4() {
442 let nested = LnmpValue::NestedArray(vec![]);
444 let result = BinaryValue::from_lnmp_value_v0_4(&nested);
445 assert!(result.is_err());
446 match result {
447 Err(BinaryError::InvalidValue { reason, .. }) => {
448 assert!(reason.contains("not supported in v0.4"));
449 }
450 _ => panic!("Expected InvalidValue error"),
451 }
452 }
453
454 #[test]
455 fn test_binary_value_to_lnmp_int() {
456 let binary_val = BinaryValue::Int(-42);
457 let lnmp_val = binary_val.to_lnmp_value();
458 assert_eq!(lnmp_val, LnmpValue::Int(-42));
459 }
460
461 #[test]
462 fn test_binary_value_to_lnmp_float() {
463 let binary_val = BinaryValue::Float(2.718);
464 let lnmp_val = binary_val.to_lnmp_value();
465 assert_eq!(lnmp_val, LnmpValue::Float(2.718));
466 }
467
468 #[test]
469 fn test_binary_value_to_lnmp_bool() {
470 let binary_val = BinaryValue::Bool(false);
471 let lnmp_val = binary_val.to_lnmp_value();
472 assert_eq!(lnmp_val, LnmpValue::Bool(false));
473 }
474
475 #[test]
476 fn test_binary_value_to_lnmp_string() {
477 let binary_val = BinaryValue::String("world".to_string());
478 let lnmp_val = binary_val.to_lnmp_value();
479 assert_eq!(lnmp_val, LnmpValue::String("world".to_string()));
480 }
481
482 #[test]
483 fn test_binary_value_to_lnmp_string_array() {
484 let binary_val = BinaryValue::StringArray(vec!["x".to_string(), "y".to_string()]);
485 let lnmp_val = binary_val.to_lnmp_value();
486 assert_eq!(
487 lnmp_val,
488 LnmpValue::StringArray(vec!["x".to_string(), "y".to_string()])
489 );
490 }
491
492 #[test]
493 fn test_binary_value_round_trip_int() {
494 let original = LnmpValue::Int(12345);
495 let binary = BinaryValue::from_lnmp_value(&original).unwrap();
496 let back = binary.to_lnmp_value();
497 assert_eq!(original, back);
498 }
499
500 #[test]
501 fn test_binary_value_round_trip_float() {
502 let original = LnmpValue::Float(1.414);
503 let binary = BinaryValue::from_lnmp_value(&original).unwrap();
504 let back = binary.to_lnmp_value();
505 assert_eq!(original, back);
506 }
507
508 #[test]
509 fn test_binary_value_round_trip_bool() {
510 let original = LnmpValue::Bool(true);
511 let binary = BinaryValue::from_lnmp_value(&original).unwrap();
512 let back = binary.to_lnmp_value();
513 assert_eq!(original, back);
514 }
515
516 #[test]
517 fn test_binary_value_round_trip_string() {
518 let original = LnmpValue::String("test".to_string());
519 let binary = BinaryValue::from_lnmp_value(&original).unwrap();
520 let back = binary.to_lnmp_value();
521 assert_eq!(original, back);
522 }
523
524 #[test]
525 fn test_binary_value_round_trip_string_array() {
526 let original = LnmpValue::StringArray(vec!["admin".to_string(), "dev".to_string()]);
527 let binary = BinaryValue::from_lnmp_value(&original).unwrap();
528 let back = binary.to_lnmp_value();
529 assert_eq!(original, back);
530 }
531
532 #[test]
533 fn test_binary_value_type_tag_int() {
534 let val = BinaryValue::Int(100);
535 assert_eq!(val.type_tag(), TypeTag::Int);
536 }
537
538 #[test]
539 fn test_binary_value_type_tag_float() {
540 let val = BinaryValue::Float(3.14);
541 assert_eq!(val.type_tag(), TypeTag::Float);
542 }
543
544 #[test]
545 fn test_binary_value_type_tag_bool() {
546 let val = BinaryValue::Bool(true);
547 assert_eq!(val.type_tag(), TypeTag::Bool);
548 }
549
550 #[test]
551 fn test_binary_value_type_tag_string() {
552 let val = BinaryValue::String("test".to_string());
553 assert_eq!(val.type_tag(), TypeTag::String);
554 }
555
556 #[test]
557 fn test_binary_value_type_tag_string_array() {
558 let val = BinaryValue::StringArray(vec!["a".to_string()]);
559 assert_eq!(val.type_tag(), TypeTag::StringArray);
560 }
561
562 #[test]
563 fn test_binary_value_type_tag_nested_record() {
564 let val = BinaryValue::NestedRecord(Box::new(LnmpRecord::new()));
565 assert_eq!(val.type_tag(), TypeTag::NestedRecord);
566 }
567
568 #[test]
569 fn test_binary_value_type_tag_nested_array() {
570 let val = BinaryValue::NestedArray(vec![]);
571 assert_eq!(val.type_tag(), TypeTag::NestedArray);
572 }
573
574 #[test]
575 fn test_binary_value_round_trip_nested_record() {
576 let mut record = LnmpRecord::new();
577 record.add_field(lnmp_core::LnmpField {
578 fid: 1,
579 value: LnmpValue::Int(42),
580 });
581 let original = LnmpValue::NestedRecord(Box::new(record));
582 let binary = BinaryValue::from_lnmp_value(&original).unwrap();
583 let back = binary.to_lnmp_value();
584 assert_eq!(original, back);
585 }
586
587 #[test]
588 fn test_binary_value_round_trip_nested_array() {
589 let mut record = LnmpRecord::new();
590 record.add_field(lnmp_core::LnmpField {
591 fid: 1,
592 value: LnmpValue::String("test".to_string()),
593 });
594 let original = LnmpValue::NestedArray(vec![record]);
595 let binary = BinaryValue::from_lnmp_value(&original).unwrap();
596 let back = binary.to_lnmp_value();
597 assert_eq!(original, back);
598 }
599
600 #[test]
601 fn test_binary_value_empty_string() {
602 let lnmp_val = LnmpValue::String("".to_string());
603 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
604 assert_eq!(binary_val, BinaryValue::String("".to_string()));
605 let back = binary_val.to_lnmp_value();
606 assert_eq!(back, lnmp_val);
607 }
608
609 #[test]
610 fn test_binary_value_empty_string_array() {
611 let lnmp_val = LnmpValue::StringArray(vec![]);
612 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
613 assert_eq!(binary_val, BinaryValue::StringArray(vec![]));
614 let back = binary_val.to_lnmp_value();
615 assert_eq!(back, lnmp_val);
616 }
617
618 #[test]
619 fn test_binary_value_negative_int() {
620 let lnmp_val = LnmpValue::Int(-9999);
621 let binary_val = BinaryValue::from_lnmp_value(&lnmp_val).unwrap();
622 assert_eq!(binary_val, BinaryValue::Int(-9999));
623 let back = binary_val.to_lnmp_value();
624 assert_eq!(back, lnmp_val);
625 }
626
627 #[test]
628 fn test_binary_value_special_floats() {
629 let nan_val = LnmpValue::Float(f64::NAN);
631 let binary_nan = BinaryValue::from_lnmp_value(&nan_val).unwrap();
632 match binary_nan {
633 BinaryValue::Float(f) => assert!(f.is_nan()),
634 _ => panic!("Expected Float variant"),
635 }
636
637 let inf_val = LnmpValue::Float(f64::INFINITY);
639 let binary_inf = BinaryValue::from_lnmp_value(&inf_val).unwrap();
640 assert_eq!(binary_inf, BinaryValue::Float(f64::INFINITY));
641
642 let neg_inf_val = LnmpValue::Float(f64::NEG_INFINITY);
644 let binary_neg_inf = BinaryValue::from_lnmp_value(&neg_inf_val).unwrap();
645 assert_eq!(binary_neg_inf, BinaryValue::Float(f64::NEG_INFINITY));
646 }
647}