1use crate::*;
2use super::*;
3#[cfg(feature = "matrix")]
4use crate::structures::Matrix;
5
6pub trait CompileConst {
10 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32>;
11}
12
13#[cfg(feature = "compiler")]
14impl CompileConst for Value {
15
16 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
17 let reg = match self {
18 #[cfg(feature = "bool")]
19 Value::Bool(x) => x.borrow().compile_const(ctx)?,
20 #[cfg(feature = "string")]
21 Value::String(x) => x.borrow().compile_const(ctx)?,
22 #[cfg(feature = "u8")]
23 Value::U8(x) => x.borrow().compile_const(ctx)?,
24 #[cfg(feature = "u16")]
25 Value::U16(x) => x.borrow().compile_const(ctx)?,
26 #[cfg(feature = "u32")]
27 Value::U32(x) => x.borrow().compile_const(ctx)?,
28 #[cfg(feature = "u64")]
29 Value::U64(x) => x.borrow().compile_const(ctx)?,
30 #[cfg(feature = "u128")]
31 Value::U128(x) => x.borrow().compile_const(ctx)?,
32 #[cfg(feature = "i8")]
33 Value::I8(x) => x.borrow().compile_const(ctx)?,
34 #[cfg(feature = "i16")]
35 Value::I16(x) => x.borrow().compile_const(ctx)?,
36 #[cfg(feature = "i32")]
37 Value::I32(x) => x.borrow().compile_const(ctx)?,
38 #[cfg(feature = "i64")]
39 Value::I64(x) => x.borrow().compile_const(ctx)?,
40 #[cfg(feature = "i128")]
41 Value::I128(x) => x.borrow().compile_const(ctx)?,
42 #[cfg(feature = "f32")]
43 Value::F32(x) => x.borrow().compile_const(ctx)?,
44 #[cfg(feature = "f64")]
45 Value::F64(x) => x.borrow().compile_const(ctx)?,
46 #[cfg(feature = "atom")]
47 Value::Atom(x) => x.borrow().compile_const(ctx)?,
48 #[cfg(feature = "index")]
49 Value::Index(x) => x.borrow().compile_const(ctx)?,
50 #[cfg(feature = "complex")]
51 Value::C64(x) => x.borrow().compile_const(ctx)?,
52 #[cfg(feature = "rational")]
53 Value::R64(x) => x.borrow().compile_const(ctx)?,
54 #[cfg(all(feature = "matrix", feature = "f64"))]
55 Value::MatrixF64(x) => x.compile_const(ctx)?,
56 #[cfg(all(feature = "matrix", feature = "f32"))]
57 Value::MatrixF32(x) => x.compile_const(ctx)?,
58 #[cfg(all(feature = "matrix", feature = "u8"))]
59 Value::MatrixU8(x) => x.compile_const(ctx)?,
60 #[cfg(all(feature = "matrix", feature = "u16"))]
61 Value::MatrixU16(x) => x.compile_const(ctx)?,
62 #[cfg(all(feature = "matrix", feature = "u32"))]
63 Value::MatrixU32(x) => x.compile_const(ctx)?,
64 #[cfg(all(feature = "matrix", feature = "u64"))]
65 Value::MatrixU64(x) => x.compile_const(ctx)?,
66 #[cfg(all(feature = "matrix", feature = "u128"))]
67 Value::MatrixU128(x) => x.compile_const(ctx)?,
68 #[cfg(all(feature = "matrix", feature = "i8"))]
69 Value::MatrixI8(x) => x.compile_const(ctx)?,
70 #[cfg(all(feature = "matrix", feature = "i16"))]
71 Value::MatrixI16(x) => x.compile_const(ctx)?,
72 #[cfg(all(feature = "matrix", feature = "i32"))]
73 Value::MatrixI32(x) => x.compile_const(ctx)?,
74 #[cfg(all(feature = "matrix", feature = "i64"))]
75 Value::MatrixI64(x) => x.compile_const(ctx)?,
76 #[cfg(all(feature = "matrix", feature = "i128"))]
77 Value::MatrixI128(x) => x.compile_const(ctx)?,
78 #[cfg(all(feature = "matrix", feature = "bool"))]
79 Value::MatrixBool(x) => x.compile_const(ctx)?,
80 #[cfg(all(feature = "matrix", feature = "rational"))]
81 Value::MatrixR64(x) => x.compile_const(ctx)?,
82 #[cfg(all(feature = "matrix", feature = "complex"))]
83 Value::MatrixC64(x) => x.compile_const(ctx)?,
84 #[cfg(all(feature = "matrix", feature = "string"))]
85 Value::MatrixString(x) => x.compile_const(ctx)?,
86 #[cfg(feature = "matrix")]
87 Value::MatrixIndex(x) => x.compile_const(ctx)?,
88 #[cfg(feature = "matrix")]
89 Value::MatrixValue(x) => x.compile_const(ctx)?,
90 #[cfg(feature = "table")]
91 Value::Table(x) => x.borrow().compile_const(ctx)?,
92 #[cfg(feature = "record")]
93 Value::Record(x) => x.borrow().compile_const(ctx)?,
94 #[cfg(feature = "set")]
95 Value::Set(x) => x.borrow().compile_const(ctx)?,
96 x => todo!("CompileConst not implemented for {:?}", x),
97 };
98 Ok(reg)
99 }
100}
101
102#[cfg(all(feature = "f64", feature = "compiler"))]
103impl CompileConst for F64 {
104 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
105 let mut payload = Vec::<u8>::new();
106 payload.write_f64::<LittleEndian>(self.0)?;
107 ctx.compile_const(&payload, ValueKind::F64)
108 }
109}
110
111#[cfg(feature = "f32")]
112impl CompileConst for F32 {
113 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
114 let mut payload = Vec::<u8>::new();
115 payload.write_f32::<LittleEndian>(self.0)?;
116 ctx.compile_const(&payload, ValueKind::F32)
117 }
118}
119
120#[cfg(feature = "u8")]
121impl CompileConst for u8 {
122 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
123 let mut payload = Vec::<u8>::new();
124 payload.write_u8(*self)?;
125 ctx.compile_const(&payload, ValueKind::U8)
126 }
127}
128
129#[cfg(feature = "i8")]
130impl CompileConst for i8 {
131 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
132 let mut payload = Vec::<u8>::new();
133 payload.write_i8(*self)?;
134 ctx.compile_const(&payload, ValueKind::I8)
135 }
136}
137
138#[cfg(feature = "compiler")]
139impl CompileConst for usize {
140 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
141 let mut payload = Vec::<u8>::new();
142 payload.write_u64::<LittleEndian>(*self as u64)?;
143 ctx.compile_const(&payload, ValueKind::Index)
144 }
145}
146
147macro_rules! impl_compile_const {
148 ($feature:literal, $t:tt) => {
149 paste! {
150 #[cfg(feature = $feature)]
151 impl CompileConst for $t {
152 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
153 let mut payload = Vec::<u8>::new();
154 payload.[<write_ $t>]::<LittleEndian>(*self)?;
155 ctx.compile_const(&payload, ValueKind::[<$t:upper>])
156 }
157 }
158 }
159 };
160}
161
162#[cfg(feature = "u16")]
163impl_compile_const!("u16", u16);
164#[cfg(feature = "u32")]
165impl_compile_const!("u32", u32);
166#[cfg(feature = "u64")]
167impl_compile_const!("u64", u64);
168#[cfg(feature = "u128")]
169impl_compile_const!("u128", u128);
170#[cfg(feature = "i16")]
171impl_compile_const!("i16", i16);
172#[cfg(feature = "i32")]
173impl_compile_const!("i32", i32);
174#[cfg(feature = "i64")]
175impl_compile_const!("i64", i64);
176#[cfg(feature = "i128")]
177impl_compile_const!("i128", i128);
178
179#[cfg(any(feature = "bool", feature = "variable_define"))]
180impl CompileConst for bool {
181 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
182 let mut payload = Vec::<u8>::new();
183 payload.write_u8(if *self { 1 } else { 0 })?;
184 ctx.compile_const(&payload, ValueKind::Bool)
185 }
186}
187
188#[cfg(any(feature = "string", feature = "variable_define"))]
189impl CompileConst for String {
190 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
191 let mut payload = Vec::<u8>::new();
192 payload.write_u32::<LittleEndian>(self.len() as u32)?;
193 payload.extend_from_slice(self.as_bytes());
194 ctx.compile_const(&payload, ValueKind::String)
195 }
196}
197
198#[cfg(feature = "rational")]
199impl CompileConst for R64 {
200 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
201 let mut payload = Vec::<u8>::new();
202 payload.write_i64::<LittleEndian>(*self.numer())?;
203 payload.write_i64::<LittleEndian>(*self.denom())?;
204 ctx.compile_const(&payload, ValueKind::R64)
205 }
206}
207
208#[cfg(feature = "complex")]
209impl CompileConst for C64 {
210 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
211 let mut payload = Vec::<u8>::new();
212 payload.write_f64::<LittleEndian>(self.0.re)?;
213 payload.write_f64::<LittleEndian>(self.0.im)?;
214 ctx.compile_const(&payload, ValueKind::C64)
215 }
216}
217
218macro_rules! impl_compile_const_matrix {
219 ($matrix_type:ty) => {
220 impl<T> CompileConst for $matrix_type
221 where
222 T: ConstElem + AsValueKind,
223 {
224 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
225 let rows = self.nrows() as u32;
226 let cols = self.ncols() as u32;
227 let mut payload = Vec::<u8>::with_capacity((rows * cols) as usize * 8);
228
229 payload.write_u32::<LittleEndian>(rows)?;
231 payload.write_u32::<LittleEndian>(cols)?;
232
233 for c in 0..cols as usize {
235 for r in 0..rows as usize {
236 self[(r, c)].write_le(&mut payload);
237 }
238 }
239 let elem_vk = T::as_value_kind();
240 let mat_vk = ValueKind::Matrix(Box::new(elem_vk), vec![rows as usize, cols as usize]);
241 ctx.compile_const(&payload, mat_vk)
242 }
243 }
244 };
245}
246
247#[cfg(feature = "matrix1")]
248impl_compile_const_matrix!(na::Matrix1<T>);
249#[cfg(feature = "matrix2")]
250impl_compile_const_matrix!(na::Matrix2<T>);
251#[cfg(feature = "matrix3")]
252impl_compile_const_matrix!(na::Matrix3<T>);
253#[cfg(feature = "matrix4")]
254impl_compile_const_matrix!(na::Matrix4<T>);
255#[cfg(feature = "matrix2x3")]
256impl_compile_const_matrix!(na::Matrix2x3<T>);
257#[cfg(feature = "matrix3x2")]
258impl_compile_const_matrix!(na::Matrix3x2<T>);
259#[cfg(feature = "row_vector2")]
260impl_compile_const_matrix!(na::RowVector2<T>);
261#[cfg(feature = "row_vector3")]
262impl_compile_const_matrix!(na::RowVector3<T>);
263#[cfg(feature = "row_vector4")]
264impl_compile_const_matrix!(na::RowVector4<T>);
265#[cfg(feature = "vector2")]
266impl_compile_const_matrix!(na::Vector2<T>);
267#[cfg(feature = "vector3")]
268impl_compile_const_matrix!(na::Vector3<T>);
269#[cfg(feature = "vector4")]
270impl_compile_const_matrix!(na::Vector4<T>);
271#[cfg(feature = "matrixd")]
272impl_compile_const_matrix!(na::DMatrix<T>);
273#[cfg(feature = "vectord")]
274impl_compile_const_matrix!(na::DVector<T>);
275#[cfg(feature = "row_vectord")]
276impl_compile_const_matrix!(na::RowDVector<T>);
277
278#[cfg(feature = "matrix")]
279impl<T> CompileConst for Matrix<T>
280where
281 T: CompileConst + ConstElem + AsValueKind
282{
283 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
284 match self {
285 #[cfg(feature = "matrixd")]
286 Matrix::DMatrix(mat) => mat.borrow().compile_const(ctx),
287 #[cfg(feature = "vectord")]
288 Matrix::DVector(mat) => mat.borrow().compile_const(ctx),
289 #[cfg(feature = "row_vectord")]
290 Matrix::RowDVector(mat) => mat.borrow().compile_const(ctx),
291 #[cfg(feature = "matrix1")]
292 Matrix::Matrix1(mat) => mat.borrow().compile_const(ctx),
293 #[cfg(feature = "matrix2")]
294 Matrix::Matrix2(mat) => mat.borrow().compile_const(ctx),
295 #[cfg(feature = "matrix3")]
296 Matrix::Matrix3(mat) => mat.borrow().compile_const(ctx),
297 #[cfg(feature = "matrix4")]
298 Matrix::Matrix4(mat) => mat.borrow().compile_const(ctx),
299 #[cfg(feature = "matrix2x3")]
300 Matrix::Matrix2x3(mat) => mat.borrow().compile_const(ctx),
301 #[cfg(feature = "matrix3x2")]
302 Matrix::Matrix3x2(mat) => mat.borrow().compile_const(ctx),
303 #[cfg(feature = "row_vector2")]
304 Matrix::RowVector2(mat) => mat.borrow().compile_const(ctx),
305 #[cfg(feature = "row_vector3")]
306 Matrix::RowVector3(mat) => mat.borrow().compile_const(ctx),
307 #[cfg(feature = "row_vector4")]
308 Matrix::RowVector4(mat) => mat.borrow().compile_const(ctx),
309 #[cfg(feature = "vector2")]
310 Matrix::Vector2(mat) => mat.borrow().compile_const(ctx),
311 #[cfg(feature = "vector3")]
312 Matrix::Vector3(mat) => mat.borrow().compile_const(ctx),
313 #[cfg(feature = "vector4")]
314 Matrix::Vector4(mat) => mat.borrow().compile_const(ctx),
315 }
316 }
317}
318
319#[cfg(feature = "matrixd")]
320impl<T> CompileConst for Ref<DMatrix<T>>
321where
322 T: CompileConst + ConstElem + AsValueKind
323{
324 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
325 self.borrow().compile_const(ctx)
326 }
327}
328
329#[cfg(feature = "vectord")]
330impl<T> CompileConst for Ref<DVector<T>>
331where
332 T: CompileConst + ConstElem + AsValueKind
333{
334 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
335 self.borrow().compile_const(ctx)
336 }
337}
338
339#[cfg(feature = "row_vectord")]
340impl<T> CompileConst for Ref<RowDVector<T>>
341where
342 T: CompileConst + ConstElem + AsValueKind
343{
344 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
345 self.borrow().compile_const(ctx)
346 }
347}
348
349#[cfg(feature = "record")]
350impl CompileConst for MechRecord {
351 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
352 let mut payload = Vec::<u8>::new();
353
354 payload.write_u32::<LittleEndian>(self.cols as u32)?;
356
357 for (col_id, value) in self.data.iter() {
359 payload.write_u64::<LittleEndian>(*col_id)?;
361 let value_kind = value.kind();
363 value_kind.write_le(&mut payload);
364 value.write_le(&mut payload);
366 }
367
368 for (_col_id, col_name) in self.field_names.iter() {
370 col_name.write_le(&mut payload);
371 }
372 ctx.compile_const(&payload, self.kind())
373 }
374}
375
376#[cfg(feature = "enum")]
377impl CompileConst for MechEnum {
378 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
379 let mut payload = Vec::<u8>::new();
380 payload.write_u64::<LittleEndian>(self.id)?;
381 payload.write_u32::<LittleEndian>(self.variants.len() as u32)?;
382 for (variant_id, variant_value) in self.variants.iter() {
383 payload.write_u64::<LittleEndian>(*variant_id)?;
384 match variant_value {
385 Some(v) => {
386 payload.write_u8(1)?;
388 let value_kind = v.kind();
390 value_kind.write_le(&mut payload);
391 v.write_le(&mut payload);
393 },
394 None => {
395 payload.write_u8(0)?;
397 }
398 }
399 }
400 ctx.compile_const(&payload, ValueKind::Enum(self.id))
401 }
402}
403
404#[cfg(feature = "atom")]
405impl CompileConst for MechAtom {
406 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
407 let mut payload = Vec::<u8>::new();
408 payload.write_u64::<LittleEndian>(self.0)?;
409 ctx.compile_const(&payload, ValueKind::Atom(self.0))
410 }
411}
412
413#[cfg(feature = "set")]
414impl CompileConst for MechSet {
415 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
416 let mut payload = Vec::<u8>::new();
417 self.kind.write_le(&mut payload);
418 payload.write_u32::<LittleEndian>(self.num_elements as u32)?;
419 for element in &self.set {
420 element.write_le(&mut payload);
421 }
422 ctx.compile_const(&payload, self.kind())
423 }
424}
425
426#[cfg(feature = "tuple")]
427impl CompileConst for MechTuple {
428 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
429 let mut payload = Vec::<u8>::new();
430 self.value_kind().write_le(&mut payload);
431 payload.write_u32::<LittleEndian>(self.elements.len() as u32)?;
432 for elem in &self.elements {
433 elem.write_le(&mut payload);
434 }
435 ctx.compile_const(&payload, self.value_kind())
436 }
437}
438
439pub trait ConstElem {
443 fn write_le(&self, out: &mut Vec<u8>);
444 fn from_le(bytes: &[u8]) -> Self;
445 fn value_kind(&self) -> ValueKind;
446 fn align() -> u8 { 1 }
447}
448
449#[cfg(feature = "f64")]
450impl ConstElem for F64 {
451 fn write_le(&self, out: &mut Vec<u8>) {
452 out.write_f64::<LittleEndian>(self.0).expect("write f64");
453 }
454 fn from_le(bytes: &[u8]) -> Self {
455 let mut rdr = std::io::Cursor::new(bytes);
456 let val = rdr.read_f64::<LittleEndian>().expect("read f64");
457 F64(val)
458 }
459 fn value_kind(&self) -> ValueKind { ValueKind::F64 }
460 fn align() -> u8 { 8 }
461}
462
463#[cfg(feature = "f32")]
464impl ConstElem for F32 {
465 fn write_le(&self, out: &mut Vec<u8>) {
466 out.write_f32::<LittleEndian>(self.0).expect("write f32");
467 }
468 fn from_le(bytes: &[u8]) -> Self {
469 let mut rdr = std::io::Cursor::new(bytes);
470 let val = rdr.read_f32::<LittleEndian>().expect("read f32");
471 F32(val)
472 }
473 fn value_kind(&self) -> ValueKind { ValueKind::F32 }
474 fn align() -> u8 { 4 }
475}
476
477macro_rules! impl_const_elem {
478 ($feature:literal, $t:ty, $align:expr) => {
479 paste!{
480 #[cfg(feature = $feature)]
481 impl ConstElem for $t {
482 fn write_le(&self, out: &mut Vec<u8>) {
483 out.[<write_ $t>]::<LittleEndian>(*self).expect(concat!("write ", stringify!($t)));
484 }
485 fn from_le(bytes: &[u8]) -> Self {
486 let mut rdr = std::io::Cursor::new(bytes);
487 rdr.[<read_ $t>]::<LittleEndian>().expect(concat!("read ", stringify!($t)))
488 }
489 fn value_kind(&self) -> ValueKind { ValueKind::[<$t:upper>] }
490 fn align() -> u8 { $align }
491 }
492 }
493 };
494}
495
496#[cfg(feature = "u16")]
497impl_const_elem!("u16", u16, 2);
498#[cfg(feature = "u32")]
499impl_const_elem!("u32", u32, 4);
500#[cfg(feature = "u64")]
501impl_const_elem!("u64", u64, 8);
502#[cfg(feature = "u128")]
503impl_const_elem!("u128", u128, 16);
504#[cfg(feature = "i16")]
505impl_const_elem!("i16", i16, 2);
506#[cfg(feature = "i32")]
507impl_const_elem!("i32", i32, 4);
508#[cfg(feature = "i64")]
509impl_const_elem!("i64", i64, 8);
510#[cfg(feature = "i128")]
511impl_const_elem!("i128", i128, 16);
512
513#[cfg(feature = "u8")]
514impl ConstElem for u8 {
515 fn write_le(&self, out: &mut Vec<u8>) {
516 out.write_u8(*self).expect("write u8");
517 }
518 fn from_le(bytes: &[u8]) -> Self {
519 bytes[0]
520 }
521 fn value_kind(&self) -> ValueKind { ValueKind::U8 }
522 fn align() -> u8 { 1 }
523}
524
525#[cfg(feature = "i8")]
526impl ConstElem for i8 {
527 fn write_le(&self, out: &mut Vec<u8>) {
528 out.write_i8(*self).expect("write i8");
529 }
530 fn from_le(bytes: &[u8]) -> Self {
531 bytes[0] as i8
532 }
533 fn value_kind(&self) -> ValueKind { ValueKind::I8 }
534 fn align() -> u8 { 1 }
535}
536
537#[cfg(feature = "rational")]
538impl ConstElem for R64 {
539 fn write_le(&self, out: &mut Vec<u8>) {
540 out.write_i64::<LittleEndian>(*self.numer()).expect("write rational numer");
541 out.write_i64::<LittleEndian>(*self.denom()).expect("write rational denom");
542 }
543 fn from_le(bytes: &[u8]) -> Self {
544 let numer = match bytes[0..8].try_into() {
545 Ok(arr) => i64::from_le_bytes(arr),
546 Err(_) => panic!("Failed to read numerator from bytes"),
547 };
548 let denom = match bytes[8..16].try_into() {
549 Ok(arr) => i64::from_le_bytes(arr),
550 Err(_) => panic!("Failed to read denominator from bytes"),
551 };
552 if denom == 0 {
553 panic!("Denominator cannot be zero");
554 }
555 R64::new(numer, denom)
556 }
557 fn value_kind(&self) -> ValueKind { ValueKind::R64 }
558 fn align() -> u8 { 16 }
559}
560
561#[cfg(feature = "complex")]
562impl ConstElem for C64 {
563 fn write_le(&self, out: &mut Vec<u8>) {
564 out.write_f64::<LittleEndian>(self.0.re).expect("write complex real");
565 out.write_f64::<LittleEndian>(self.0.im).expect("write complex imag");
566 }
567 fn from_le(bytes: &[u8]) -> Self {
568 let real = match bytes[0..8].try_into() {
569 Ok(arr) => f64::from_le_bytes(arr),
570 Err(_) => panic!("Failed to read real part from bytes"),
571 };
572 let imag = match bytes[8..16].try_into() {
573 Ok(arr) => f64::from_le_bytes(arr),
574 Err(_) => panic!("Failed to read imaginary part from bytes"),
575 };
576 C64::new(real, imag)
577 }
578 fn value_kind(&self) -> ValueKind { ValueKind::C64 }
579 fn align() -> u8 { 16 }
580}
581
582#[cfg(feature = "string")]
583impl ConstElem for String {
584 fn write_le(&self, out: &mut Vec<u8>) {
585 use byteorder::{LittleEndian, WriteBytesExt};
586 out.write_u32::<LittleEndian>(self.len() as u32).expect("write string length");
587 out.extend_from_slice(self.as_bytes());
588 }
589 fn from_le(bytes: &[u8]) -> Self {
590 use byteorder::{LittleEndian, ReadBytesExt};
591 use std::io::Cursor;
592 let mut cursor = Cursor::new(bytes);
593 let len = match cursor.read_u32::<LittleEndian>() {
595 Ok(n) => n as usize,
596 Err(_) => panic!("Failed to read string length from bytes"),
597 };
598 let start = cursor.position() as usize;
599 let end = start + len;
600 if end > bytes.len() {
601 panic!(
602 "String::from_le: declared length {} exceeds available bytes ({})",
603 len, bytes.len()
604 );
605 }
606 let str_bytes = &bytes[start..end];
607 match std::str::from_utf8(str_bytes) {
608 Ok(s) => s.to_string(),
609 Err(_) => panic!("Failed to convert bytes to UTF-8 string"),
610 }
611 }
612 fn value_kind(&self) -> ValueKind { ValueKind::String }
613 fn align() -> u8 { 1 }
614}
615
616#[cfg(feature = "bool")]
617impl ConstElem for bool {
618 fn write_le(&self, out: &mut Vec<u8>) {
619 out.write_u8(if *self { 1 } else { 0 }).expect("write bool");
620 }
621 fn from_le(bytes: &[u8]) -> Self {
622 bytes[0] != 0
623 }
624 fn value_kind(&self) -> ValueKind { ValueKind::Bool }
625 fn align() -> u8 { 1 }
626}
627
628impl ConstElem for usize {
629 fn write_le(&self, out: &mut Vec<u8>) {
630 out.write_u64::<LittleEndian>(*self as u64).expect("write usize");
631 }
632 fn from_le(bytes: &[u8]) -> Self {
633 let val = match bytes[0..8].try_into() {
634 Ok(arr) => u64::from_le_bytes(arr),
635 Err(_) => panic!("Failed to read usize from bytes"),
636 };
637 val as usize
638 }
639 fn value_kind(&self) -> ValueKind { ValueKind::Index }
640 fn align() -> u8 { 8 }
641}
642
643macro_rules! impl_const_elem_matrix {
644 ($matrix_type:ty) => {
645 impl<T> ConstElem for $matrix_type
646 where
647 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
648 {
649 fn write_le(&self, out: &mut Vec<u8>) {
650 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
651 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
652 for c in 0..self.ncols() {
653 for r in 0..self.nrows() {
654 self[(r, c)].write_le(out);
655 }
656 }
657 }
658 fn from_le(bytes: &[u8]) -> Self {
659 let mut cursor = Cursor::new(bytes);
660 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
661 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
662 let mut elements: Vec<T> = Vec::with_capacity(rows * cols);
663
664 for _c in 0..cols {
666 for _r in 0..rows {
667 let elem = T::from_le(&bytes[cursor.position() as usize..]);
668 let mut buf = Vec::new();
669 elem.write_le(&mut buf);
670 cursor.set_position(cursor.position() + buf.len() as u64);
671 elements.push(elem);
672 }
673 }
674 <$matrix_type>::from_row_slice(&elements)
677 }
678 fn value_kind(&self) -> ValueKind { self.value_kind() }
679 fn align() -> u8 { 8 }
680 }
681 };
682}
683
684#[cfg(feature = "matrixd")]
685impl<T> ConstElem for DMatrix<T>
686where
687 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
688{
689 fn write_le(&self, out: &mut Vec<u8>) {
690 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
691 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
692 for c in 0..self.ncols() {
693 for r in 0..self.nrows() {
694 self[(r, c)].write_le(out);
695 }
696 }
697 }
698 fn from_le(bytes: &[u8]) -> Self {
699 let mut cursor = Cursor::new(bytes);
700 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
701 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
702 let mut elements = Vec::with_capacity(rows * cols);
703 for _c in 0..cols {
705 for _r in 0..rows {
706 let elem = T::from_le(&bytes[cursor.position() as usize..]);
707 let mut buf = Vec::new();
708 elem.write_le(&mut buf);
709 cursor.set_position(cursor.position() + buf.len() as u64);
710 elements.push(elem);
711 }
712 }
713 DMatrix::from_vec(rows, cols, elements)
714 }
715 fn value_kind(&self) -> ValueKind { self.value_kind() }
716 fn align() -> u8 { 8 }
717}
718
719#[cfg(feature = "vectord")]
720impl<T> ConstElem for DVector<T>
721where
722 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
723{
724 fn write_le(&self, out: &mut Vec<u8>) {
725 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
726 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
727 for c in 0..self.ncols() {
728 for r in 0..self.nrows() {
729 self[(r, c)].write_le(out);
730 }
731 }
732 }
733 fn from_le(bytes: &[u8]) -> Self {
734 let mut cursor = Cursor::new(bytes);
735 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
736 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
737 let mut elements = Vec::with_capacity(rows * cols);
738 for _c in 0..cols {
740 for _r in 0..rows {
741 let elem = T::from_le(&bytes[cursor.position() as usize..]);
742 let mut buf = Vec::new();
743 elem.write_le(&mut buf);
744 cursor.set_position(cursor.position() + buf.len() as u64);
745 elements.push(elem);
746 }
747 }
748 DVector::from_vec(elements)
749 }
750 fn value_kind(&self) -> ValueKind { self.value_kind() }
751 fn align() -> u8 { 8 }
752}
753
754#[cfg(feature = "row_vectord")]
755impl<T> ConstElem for RowDVector<T>
756where
757 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
758{
759 fn write_le(&self, out: &mut Vec<u8>) {
760 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
761 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
762 for c in 0..self.ncols() {
763 for r in 0..self.nrows() {
764 self[(r, c)].write_le(out);
765 }
766 }
767 }
768 fn from_le(bytes: &[u8]) -> Self {
769 let mut cursor = Cursor::new(bytes);
770 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
771 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
772 let mut elements = Vec::with_capacity(rows * cols);
773 for _c in 0..cols {
775 for _r in 0..rows {
776 let elem = T::from_le(&bytes[cursor.position() as usize..]);
777 let mut buf = Vec::new();
778 elem.write_le(&mut buf);
779 cursor.set_position(cursor.position() + buf.len() as u64);
780 elements.push(elem);
781 }
782 }
783 RowDVector::from_vec(elements)
784 }
785 fn value_kind(&self) -> ValueKind { self.value_kind() }
786 fn align() -> u8 { 8 }
787}
788
789#[cfg(feature = "matrix1")]
790impl_const_elem_matrix!(Matrix1<T>);
791#[cfg(feature = "matrix2")]
792impl_const_elem_matrix!(Matrix2<T>);
793#[cfg(feature = "matrix3")]
794impl_const_elem_matrix!(Matrix3<T>);
795#[cfg(feature = "matrix4")]
796impl_const_elem_matrix!(Matrix4<T>);
797#[cfg(feature = "matrix2x3")]
798impl_const_elem_matrix!(Matrix2x3<T>);
799#[cfg(feature = "matrix3x2")]
800impl_const_elem_matrix!(Matrix3x2<T>);
801#[cfg(feature = "row_vector2")]
802impl_const_elem_matrix!(RowVector2<T>);
803#[cfg(feature = "row_vector3")]
804impl_const_elem_matrix!(RowVector3<T>);
805#[cfg(feature = "row_vector4")]
806impl_const_elem_matrix!(RowVector4<T>);
807#[cfg(feature = "vector2")]
808impl_const_elem_matrix!(Vector2<T>);
809#[cfg(feature = "vector3")]
810impl_const_elem_matrix!(Vector3<T>);
811#[cfg(feature = "vector4")]
812impl_const_elem_matrix!(Vector4<T>);
813
814#[cfg(feature = "matrix")]
815impl<T> ConstElem for Matrix<T>
816where
817 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
818{
819 fn write_le(&self, out: &mut Vec<u8>) {
820 match self {
821 #[cfg(feature = "matrixd")]
822 Matrix::DMatrix(mat) => mat.borrow().write_le(out),
823 #[cfg(feature = "vectord")]
824 Matrix::DVector(mat) => mat.borrow().write_le(out),
825 #[cfg(feature = "row_vectord")]
826 Matrix::RowDVector(mat) => mat.borrow().write_le(out),
827 #[cfg(feature = "matrix1")]
828 Matrix::Matrix1(mat) => mat.borrow().write_le(out),
829 #[cfg(feature = "matrix2")]
830 Matrix::Matrix2(mat) => mat.borrow().write_le(out),
831 #[cfg(feature = "matrix3")]
832 Matrix::Matrix3(mat) => mat.borrow().write_le(out),
833 #[cfg(feature = "matrix4")]
834 Matrix::Matrix4(mat) => mat.borrow().write_le(out),
835 #[cfg(feature = "matrix2x3")]
836 Matrix::Matrix2x3(mat) => mat.borrow().write_le(out),
837 #[cfg(feature = "matrix3x2")]
838 Matrix::Matrix3x2(mat) => mat.borrow().write_le(out),
839 #[cfg(feature = "row_vector2")]
840 Matrix::RowVector2(mat) => mat.borrow().write_le(out),
841 #[cfg(feature = "row_vector3")]
842 Matrix::RowVector3(mat) => mat.borrow().write_le(out),
843 #[cfg(feature = "row_vector4")]
844 Matrix::RowVector4(mat) => mat.borrow().write_le(out),
845 #[cfg(feature = "vector2")]
846 Matrix::Vector2(mat) => mat.borrow().write_le(out),
847 #[cfg(feature = "vector3")]
848 Matrix::Vector3(mat) => mat.borrow().write_le(out),
849 #[cfg(feature = "vector4")]
850 Matrix::Vector4(mat) => mat.borrow().write_le(out),
851 }
852 }
853 fn from_le(bytes: &[u8]) -> Self {
854 let mut cursor = Cursor::new(bytes);
855 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
856 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
857 let mut elements = Vec::with_capacity(rows * cols);
858 for _c in 0..cols {
860 for _r in 0..rows {
861 let elem = T::from_le(&bytes[cursor.position() as usize..]);
862 let mut buf = Vec::new();
863 elem.write_le(&mut buf);
864 cursor.set_position(cursor.position() + buf.len() as u64);
865 elements.push(elem);
866 }
867 }
868 if rows == 0 || cols == 0 {
869 panic!("Cannot create Matrix with zero rows or columns");
870 } else if cols == 1 {
871 match rows {
872 #[cfg(feature = "matrix1")]
873 1 => Matrix::Matrix1(Ref::new(Matrix1::from_vec(elements))),
874 #[cfg(all(feature = "matrixd", not(feature = "matrix1")))]
875 1 => Matrix::DMatrix(Ref::new(DMatrix::from_vec(1,1, elements))),
876 #[cfg(feature = "vector2")]
877 2 => Matrix::Vector2(Ref::new(Vector2::from_vec(elements))),
878 #[cfg(feature = "vector3")]
879 3 => Matrix::Vector3(Ref::new(Vector3::from_vec(elements))),
880 #[cfg(feature = "vector4")]
881 4 => Matrix::Vector4(Ref::new(Vector4::from_vec(elements))),
882 #[cfg(feature = "vectord")]
883 _ => Matrix::DVector(Ref::new(DVector::from_vec(elements))),
884 _ => panic!("No suitable Matrix variant for dimensions {}x{}", rows, cols),
885 }
886 } else if rows == 1 {
887 match cols {
888 #[cfg(feature = "row_vector2")]
889 2 => Matrix::RowVector2(Ref::new(RowVector2::from_vec(elements))),
890 #[cfg(feature = "row_vector3")]
891 3 => Matrix::RowVector3(Ref::new(RowVector3::from_vec(elements))),
892 #[cfg(feature = "row_vector4")]
893 4 => Matrix::RowVector4(Ref::new(RowVector4::from_vec(elements))),
894 #[cfg(feature = "row_vectord")]
895 _ => Matrix::RowDVector(Ref::new(RowDVector::from_vec(elements))),
896 _ => panic!("No suitable Matrix variant for dimensions {}x{}", rows, cols),
897 }
898 } else {
899 match (rows, cols) {
900 #[cfg(feature = "matrix1")]
901 (1, 1) => Matrix::Matrix1(Ref::new(Matrix1::from_row_slice(&elements))),
902 #[cfg(feature = "matrix2")]
903 (2, 2) => Matrix::Matrix2(Ref::new(Matrix2::from_row_slice(&elements))),
904 #[cfg(feature = "matrix3")]
905 (3, 3) => Matrix::Matrix3(Ref::new(Matrix3::from_row_slice(&elements))),
906 #[cfg(feature = "matrix4")]
907 (4, 4) => Matrix::Matrix4(Ref::new(Matrix4::from_row_slice(&elements))),
908 #[cfg(feature = "matrix2x3")]
909 (2, 3) => Matrix::Matrix2x3(Ref::new(Matrix2x3::from_row_slice(&elements))),
910 #[cfg(feature = "matrix3x2")]
911 (3, 2) => Matrix::Matrix3x2(Ref::new(Matrix3x2::from_row_slice(&elements))),
912 #[cfg(feature = "matrixd")]
913 _ => Matrix::DMatrix(Ref::new(DMatrix::from_vec(rows, cols, elements))),
914 _ => panic!("No suitable Matrix variant for dimensions {}x{}", rows, cols),
915 }
916 }
917 }
918 fn value_kind(&self) -> ValueKind { self.value_kind() }
919 fn align() -> u8 { T::align() }
920}
921
922
923impl ConstElem for Value {
924 fn write_le(&self, out: &mut Vec<u8>) {
925 self.kind().write_le(out);
927
928 match self {
930 Value::Empty => {
931 },
933 #[cfg(feature = "bool")]
934 Value::Bool(x) => x.borrow().write_le(out),
935 #[cfg(feature = "string")]
936 Value::String(x) => x.borrow().write_le(out),
937 #[cfg(feature = "u8")]
938 Value::U8(x) => x.borrow().write_le(out),
939 #[cfg(feature = "u16")]
940 Value::U16(x) => x.borrow().write_le(out),
941 #[cfg(feature = "u32")]
942 Value::U32(x) => x.borrow().write_le(out),
943 #[cfg(feature = "u64")]
944 Value::U64(x) => x.borrow().write_le(out),
945 #[cfg(feature = "u128")]
946 Value::U128(x) => x.borrow().write_le(out),
947 #[cfg(feature = "i8")]
948 Value::I8(x) => x.borrow().write_le(out),
949 #[cfg(feature = "i16")]
950 Value::I16(x) => x.borrow().write_le(out),
951 #[cfg(feature = "i32")]
952 Value::I32(x) => x.borrow().write_le(out),
953 #[cfg(feature = "i64")]
954 Value::I64(x) => x.borrow().write_le(out),
955 #[cfg(feature = "i128")]
956 Value::I128(x) => x.borrow().write_le(out),
957 #[cfg(feature = "f32")]
958 Value::F32(x) => x.borrow().write_le(out),
959 #[cfg(feature = "f64")]
960 Value::F64(x) => x.borrow().write_le(out),
961 #[cfg(feature = "rational")]
962 Value::R64(x) => x.borrow().write_le(out),
963 #[cfg(feature = "complex")]
964 Value::C64(x) => x.borrow().write_le(out),
965 #[cfg(feature = "set")]
966 Value::Set(x) => x.borrow().write_le(out),
967 _ => unimplemented!("write_le not implemented for this Value variant"),
968 }
969 }
970 fn from_le(bytes: &[u8]) -> Self {
971 let mut cursor = std::io::Cursor::new(bytes);
972
973 let kind = ValueKind::from_le(cursor.get_ref());
975
976 let mut kind_buf = Vec::new();
978 kind.write_le(&mut kind_buf);
979 let payload = &bytes[kind_buf.len()..];
980
981 match kind {
983 ValueKind::Empty => Value::Empty,
984 #[cfg(feature = "bool")]
985 ValueKind::Bool => Value::Bool(Ref::new(<bool as ConstElem>::from_le(payload))),
986 #[cfg(feature = "string")]
987 ValueKind::String => Value::String(Ref::new(<String as ConstElem>::from_le(payload))),
988 #[cfg(feature = "u8")]
989 ValueKind::U8 => Value::U8(Ref::new(<u8 as ConstElem>::from_le(payload))),
990 #[cfg(feature = "u16")]
991 ValueKind::U16 => Value::U16(Ref::new(<u16 as ConstElem>::from_le(payload))),
992 #[cfg(feature = "u32")]
993 ValueKind::U32 => Value::U32(Ref::new(<u32 as ConstElem>::from_le(payload))),
994 #[cfg(feature = "u64")]
995 ValueKind::U64 => Value::U64(Ref::new(<u64 as ConstElem>::from_le(payload))),
996 #[cfg(feature = "u128")]
997 ValueKind::U128 => Value::U128(Ref::new(<u128 as ConstElem>::from_le(payload))),
998 #[cfg(feature = "i8")]
999 ValueKind::I8 => Value::I8(Ref::new(<i8 as ConstElem>::from_le(payload))),
1000 #[cfg(feature = "i16")]
1001 ValueKind::I16 => Value::I16(Ref::new(<i16 as ConstElem>::from_le(payload))),
1002 #[cfg(feature = "i32")]
1003 ValueKind::I32 => Value::I32(Ref::new(<i32 as ConstElem>::from_le(payload))),
1004 #[cfg(feature = "i64")]
1005 ValueKind::I64 => Value::I64(Ref::new(<i64 as ConstElem>::from_le(payload))),
1006 #[cfg(feature = "i128")]
1007 ValueKind::I128 => Value::I128(Ref::new(<i128 as ConstElem>::from_le(payload))),
1008 #[cfg(feature = "f32")]
1009 ValueKind::F32 => Value::F32(Ref::new(<F32 as ConstElem>::from_le(payload))),
1010 #[cfg(feature = "f64")]
1011 ValueKind::F64 => Value::F64(Ref::new(<F64 as ConstElem>::from_le(payload))),
1012 #[cfg(feature = "rational")]
1013 ValueKind::R64 => Value::R64(Ref::new(<R64 as ConstElem>::from_le(payload))),
1014 #[cfg(feature = "complex")]
1015 ValueKind::C64 => Value::C64(Ref::new(<C64 as ConstElem>::from_le(payload))),
1016 x => unimplemented!("from_le not implemented for this ValueKind variant: {:?}", x),
1017 }
1018 }
1019 fn value_kind(&self) -> ValueKind {
1020 self.value_kind()
1021 }
1022 fn align() -> u8 {
1023 1
1024 }
1025}
1026
1027impl ConstElem for ValueKind {
1028 fn write_le(&self, out: &mut Vec<u8>) {
1029 match self {
1030 ValueKind::U8 => out.write_u8(1).expect("write value kind"),
1031 ValueKind::U16 => out.write_u8(2).expect("write value kind"),
1032 ValueKind::U32 => out.write_u8(3).expect("write value kind"),
1033 ValueKind::U64 => out.write_u8(4).expect("write value kind"),
1034 ValueKind::U128 => out.write_u8(5).expect("write value kind"),
1035 ValueKind::I8 => out.write_u8(6).expect("write value kind"),
1036 ValueKind::I16 => out.write_u8(7).expect("write value kind"),
1037 ValueKind::I32 => out.write_u8(8).expect("write value kind"),
1038 ValueKind::I64 => out.write_u8(9).expect("write value kind"),
1039 ValueKind::I128 => out.write_u8(10).expect("write value kind"),
1040 ValueKind::F32 => out.write_u8(11).expect("write value kind"),
1041 ValueKind::F64 => out.write_u8(12).expect("write value kind"),
1042 ValueKind::C64 => out.write_u8(13).expect("write value kind"),
1043 ValueKind::R64 => out.write_u8(14).expect("write value kind"),
1044 ValueKind::String => out.write_u8(15).expect("write value kind"),
1045 ValueKind::Bool => out.write_u8(16).expect("write value kind"),
1046 ValueKind::Id => out.write_u8(17).expect("write value kind"),
1047 ValueKind::Index => out.write_u8(18).expect("write value kind"),
1048 ValueKind::Empty => out.write_u8(19).expect("write value kind"),
1049 ValueKind::Any => out.write_u8(20).expect("write value kind"),
1050 ValueKind::Matrix(elem_vk, dims) => {
1051 out.write_u8(21).expect("write value kind");
1052 elem_vk.write_le(out);
1053 out.write_u32::<LittleEndian>(dims.len() as u32).expect("write matrix dims length");
1054 for d in dims.iter() {
1055 out.write_u32::<LittleEndian>(*d as u32).expect("write matrix dim");
1056 }
1057 },
1058 ValueKind::Enum(id) => {
1059 out.write_u8(22).expect("write value kind");
1060 out.write_u64::<LittleEndian>(*id).expect("write enum id");
1061 },
1062 #[cfg(feature = "record")]
1063 ValueKind::Record(fields) => {
1064 out.write_u8(23).expect("write value kind");
1065 out.write_u32::<LittleEndian>(fields.len() as u32).expect("write record fields length");
1066 for (name, vk) in fields.iter() {
1067 name.write_le(out);
1068 vk.write_le(out);
1069 }
1070 },
1071 ValueKind::Map(key_vk, val_vk) => {
1072 out.write_u8(24).expect("write value kind");
1073 key_vk.write_le(out);
1074 val_vk.write_le(out);
1075 },
1076 ValueKind::Atom(id) => {
1077 out.write_u8(25).expect("write value kind");
1078 out.write_u64::<LittleEndian>(*id).expect("write atom id");
1079 },
1080 #[cfg(feature = "table")]
1081 ValueKind::Table(fields, row_count) => {
1082 out.write_u8(26).expect("write value kind");
1083 out.write_u32::<LittleEndian>(fields.len() as u32).expect("write table fields length");
1084 for (name, vk) in fields.iter() {
1085 name.write_le(out);
1086 vk.write_le(out);
1087 }
1088 out.write_u32::<LittleEndian>(*row_count as u32).expect("write table row count");
1089 },
1090 ValueKind::Tuple(vks) => {
1091 out.write_u8(27).expect("write value kind");
1092 out.write_u32::<LittleEndian>(vks.len() as u32).expect("write tuple length");
1093 for vk in vks.iter() {
1094 vk.write_le(out);
1095 }
1096 },
1097 ValueKind::Reference(vk) => {
1098 out.write_u8(28).expect("write value kind");
1099 vk.write_le(out);
1100 },
1101 ValueKind::Set(vk, opt_size) => {
1102 out.write_u8(29).expect("write value kind");
1103 vk.write_le(out);
1104 match opt_size {
1105 Some(sz) => {
1106 out.write_u8(1).expect("write set size flag");
1107 out.write_u32::<LittleEndian>(*sz as u32).expect("write set size");
1108 },
1109 None => {
1110 out.write_u8(0).expect("write set size flag");
1111 }
1112 }
1113 },
1114 ValueKind::Option(vk) => {
1115 out.write_u8(30).expect("write value kind");
1116 vk.write_le(out);
1117 },
1118 _ => unimplemented!("write_le not implemented for this ValueKind variant"),
1119 }
1120 }
1121 fn from_le(bytes: &[u8]) -> Self {
1122 let mut cursor = Cursor::new(bytes);
1123 let tag = cursor.read_u8().expect("read value kind tag");
1124
1125 match tag {
1126 0 => ValueKind::Empty,
1127 1 => ValueKind::U8,
1128 2 => ValueKind::U16,
1129 3 => ValueKind::U32,
1130 4 => ValueKind::U64,
1131 5 => ValueKind::U128,
1132 6 => ValueKind::I8,
1133 7 => ValueKind::I16,
1134 8 => ValueKind::I32,
1135 9 => ValueKind::I64,
1136 10 => ValueKind::I128,
1137 11 => ValueKind::F32,
1138 12 => ValueKind::F64,
1139 13 => ValueKind::C64,
1140 14 => ValueKind::R64,
1141 15 => ValueKind::String,
1142 16 => ValueKind::Bool,
1143 17 => ValueKind::Id,
1144 18 => ValueKind::Index,
1145 19 => ValueKind::Empty,
1146 20 => ValueKind::Any,
1147 #[cfg(feature = "matrix")]
1148 21 => {
1149 let elem_vk = ValueKind::from_le(&bytes[cursor.position() as usize..]);
1150 cursor.set_position(cursor.position() + 1); let dim_count = cursor.read_u32::<LittleEndian>().expect("read matrix dim count") as usize;
1152 let mut dims = Vec::with_capacity(dim_count);
1153 for _ in 0..dim_count {
1154 dims.push(cursor.read_u32::<LittleEndian>().expect("read matrix dim") as usize);
1155 }
1156 ValueKind::Matrix(Box::new(elem_vk), dims)
1157 }
1158 #[cfg(feature = "enum")]
1159 22 => ValueKind::Enum(cursor.read_u64::<LittleEndian>().expect("read enum id")),
1160 #[cfg(feature = "table")]
1161 26 => {
1162 let field_count = cursor.read_u32::<LittleEndian>().expect("read table fields length") as usize;
1163 let mut fields = Vec::with_capacity(field_count);
1164 for _ in 0..field_count {
1165 let name = String::from_le(&bytes[cursor.position() as usize..]);
1166 let mut buf = Vec::new();
1167 name.write_le(&mut buf);
1168 cursor.set_position(cursor.position() + buf.len() as u64);
1169 let vk = ValueKind::from_le(&bytes[cursor.position() as usize..]);
1170 let mut buf = Vec::new();
1171 vk.write_le(&mut buf);
1172 cursor.set_position(cursor.position() + buf.len() as u64);
1173 fields.push((name, vk));
1174 }
1175 let row_count = cursor.read_u32::<LittleEndian>().expect("read table row count") as usize;
1176 ValueKind::Table(fields, row_count)
1177 }
1178 #[cfg(feature = "set")]
1179 29 => {
1180 let elem_vk = ValueKind::from_le(&bytes[cursor.position() as usize..]);
1181 cursor.set_position(cursor.position() + 1);
1182 let size_flag = cursor.read_u8().expect("read set size flag");
1183 let opt_size = if size_flag != 0 {
1184 Some(cursor.read_u32::<LittleEndian>().expect("read set size") as usize)
1185 } else {
1186 None
1187 };
1188 ValueKind::Set(Box::new(elem_vk), opt_size)
1189 }
1190 x => unimplemented!("from_le not implemented for this ValueKind variant: {:?}", x),
1191 }
1192 }
1193 fn value_kind(&self) -> ValueKind { self.clone() }
1194 fn align() -> u8 { 1 }
1195}
1196
1197fn read_string_from_cursor(cursor: &mut std::io::Cursor<&[u8]>) -> Vec<u8> {
1199 let len = cursor.read_u32::<LittleEndian>().expect("read string len") as usize;
1200 let mut buf = vec![0u8; len];
1201 cursor.read_exact(&mut buf).expect("read string bytes");
1202 buf
1203}
1204
1205#[cfg(feature = "enum")]
1206impl ConstElem for MechEnum {
1207 fn write_le(&self, out: &mut Vec<u8>) {
1208 out.write_u64::<LittleEndian>(self.id).expect("write enum id");
1210
1211 out.write_u32::<LittleEndian>(self.variants.len() as u32).expect("write enum variants length");
1213
1214 for (variant_id, variant_value) in self.variants.iter() {
1216 out.write_u64::<LittleEndian>(*variant_id).expect("write enum variant id");
1218 match variant_value {
1219 Some(v) => {
1220 out.write_u8(1).expect("write enum variant has value");
1222 let value_kind = v.kind();
1224 value_kind.write_le(out);
1225 v.write_le(out);
1227 },
1228 None => {
1229 out.write_u8(0).expect("write enum variant has no value");
1231 }
1232 }
1233 }
1234 }
1235 fn from_le(_bytes: &[u8]) -> Self {
1236 unimplemented!("from_le not implemented for MechEnum")
1237 }
1238 fn value_kind(&self) -> ValueKind { ValueKind::Enum(0) } fn align() -> u8 { 8 }
1240}
1241
1242#[cfg(feature = "table")]
1243impl ConstElem for MechTable {
1244 fn write_le(&self, out: &mut Vec<u8>) {
1245 self.value_kind().write_le(out);
1247 out.write_u32::<LittleEndian>(self.rows as u32).expect("write table rows");
1249 out.write_u32::<LittleEndian>(self.cols as u32).expect("write table cols");
1250 for (col_id, (vk, col_data)) in &self.data {
1252 out.write_u64::<LittleEndian>(*col_id).expect("write column id");
1254 vk.write_le(out);
1256 col_data.write_le(out);
1258 if let Some(name) = self.col_names.get(col_id) {
1260 name.write_le(out);
1261 } else {
1262 String::from("").write_le(out);
1263 }
1264 }
1265 }
1266 fn from_le(data: &[u8]) -> Self {
1267 use indexmap::IndexMap;
1268 let mut cursor = Cursor::new(data);
1269 let kind = ValueKind::from_le(cursor.get_ref());
1271 let mut buf = Vec::new();
1272 kind.write_le(&mut buf);
1273 cursor.set_position(buf.len() as u64);
1274
1275 let rows = cursor.read_u32::<LittleEndian>().expect("read rows") as usize;
1277 let cols = cursor.read_u32::<LittleEndian>().expect("read cols") as usize;
1278
1279 let mut data_map: IndexMap<u64, (ValueKind, Matrix<Value>)> = IndexMap::new();
1280 let mut col_names: HashMap<u64, String> = HashMap::new();
1281
1282 for _ in 0..cols {
1284 let col_id = cursor.read_u64::<LittleEndian>().expect("read column id");
1285
1286 let kind = ValueKind::from_le(&data[cursor.position() as usize..]);
1288 let mut tmp = Vec::new();
1289 kind.write_le(&mut tmp);
1290 cursor.set_position(cursor.position() + tmp.len() as u64);
1291
1292 let matrix = Matrix::<Value>::from_le(&data[cursor.position() as usize..]);
1294 let mut tmp = Vec::new();
1295 matrix.write_le(&mut tmp);
1296 cursor.set_position(cursor.position() + tmp.len() as u64);
1297
1298 let name = String::from_le(&data[cursor.position() as usize..]);
1300 let mut tmp = Vec::new();
1301 name.write_le(&mut tmp);
1302 cursor.set_position(cursor.position() + tmp.len() as u64);
1303
1304 data_map.insert(col_id, (kind, matrix));
1305 col_names.insert(col_id, name);
1306 }
1307
1308 MechTable { rows, cols, data: data_map, col_names }
1309 }
1310 fn value_kind(&self) -> ValueKind { self.kind() }
1311 fn align() -> u8 { 8 }
1312}
1313
1314#[cfg(feature = "table")]
1315impl CompileConst for MechTable {
1316 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
1317 let mut payload = Vec::<u8>::new();
1318 self.value_kind().write_le(&mut payload);
1319 payload.write_u32::<LittleEndian>(self.rows as u32)?;
1320 payload.write_u32::<LittleEndian>(self.cols as u32)?;
1321 for (col_id, (vk, col_data)) in &self.data {
1322 payload.write_u64::<LittleEndian>(*col_id)?;
1323 vk.write_le(&mut payload);
1324 col_data.write_le(&mut payload);
1325
1326 if let Some(name) = self.col_names.get(col_id) {
1327 name.write_le(&mut payload);
1328 } else {
1329 String::from("").write_le(&mut payload);
1330 }
1331 }
1332 ctx.compile_const(&payload, self.value_kind())
1333 }
1334}
1335
1336#[cfg(feature = "set")]
1337impl ConstElem for MechSet {
1338 fn write_le(&self, out: &mut Vec<u8>) {
1339 self.kind.write_le(out);
1341 out.write_u32::<LittleEndian>(self.num_elements as u32)
1343 .expect("write set element count");
1344 for value in &self.set {
1346 value.write_le(out);
1347 }
1348 }
1349 fn from_le(data: &[u8]) -> Self {
1350 use indexmap::IndexSet;
1351 let mut cursor = Cursor::new(data);
1352 let start = cursor.position() as usize;
1354 let kind = ValueKind::from_le(&data[start..]);
1355 let mut kind_buf = Vec::new();
1357 kind.write_le(&mut kind_buf);
1358 cursor.set_position(start as u64 + kind_buf.len() as u64);
1359 let num_elements = cursor
1361 .read_u32::<LittleEndian>()
1362 .expect("read set element count") as usize;
1363 let mut set = IndexSet::with_capacity(num_elements);
1365 for _ in 0..num_elements {
1366 let pos = cursor.position() as usize;
1367 let value = Value::from_le(&data[pos..]);
1368 let mut tmp = Vec::new();
1370 value.write_le(&mut tmp);
1371 cursor.set_position(pos as u64 + tmp.len() as u64);
1372 set.insert(value);
1373 }
1374 Self { kind, num_elements, set }
1375 }
1376 fn value_kind(&self) -> ValueKind { self.kind.clone() }
1377 fn align() -> u8 { 8 }
1378}
1379
1380#[cfg(feature = "tuple")]
1381impl ConstElem for MechTuple {
1382 fn write_le(&self, out: &mut Vec<u8>) {
1383 self.value_kind().write_le(out);
1384 out.write_u32::<LittleEndian>(self.elements.len() as u32)
1385 .expect("write tuple element count");
1386 for elem in &self.elements {
1387 elem.write_le(out);
1388 }
1389 }
1390 fn from_le(data: &[u8]) -> Self {
1391 let mut cursor = Cursor::new(data);
1392 let start = cursor.position() as usize;
1394 let kind = ValueKind::from_le(&data[start..]);
1395 let mut kind_buf = Vec::new();
1397 kind.write_le(&mut kind_buf);
1398 cursor.set_position(start as u64 + kind_buf.len() as u64);
1399 let num_elements = cursor
1401 .read_u32::<LittleEndian>()
1402 .expect("read tuple element count") as usize;
1403 let mut elements: Vec<Box<Value>> = Vec::with_capacity(num_elements);
1405 for _ in 0..num_elements {
1406 let pos = cursor.position() as usize;
1407 let value = Value::from_le(&data[pos..]);
1408 let mut tmp = Vec::new();
1410 value.write_le(&mut tmp);
1411 cursor.set_position(pos as u64 + tmp.len() as u64);
1412 elements.push(Box::new(value));
1413 }
1414 Self { elements }
1415 }
1416 fn value_kind(&self) -> ValueKind {
1417 ValueKind::Tuple(
1418 self.elements
1419 .iter()
1420 .map(|v| v.value_kind())
1421 .collect::<Vec<_>>()
1422 )
1423 }
1424 fn align() -> u8 { 8 }
1425}