mech_core/program/compiler/
constants.rs

1use crate::*;
2use super::*;
3#[cfg(feature = "matrix")]
4use crate::structures::Matrix;
5
6// CompileConst Trait
7// ----------------------------------------------------------------------------
8
9pub 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      _ => todo!(),
93    };
94    Ok(reg)
95  }
96}
97
98#[cfg(feature = "f64")]
99impl CompileConst for F64 {
100  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
101    let mut payload = Vec::<u8>::new();
102    payload.write_f64::<LittleEndian>(self.0)?;
103    ctx.compile_const(&payload, ValueKind::F64)
104  }
105}
106
107#[cfg(feature = "f32")]
108impl CompileConst for F32 {
109  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
110    let mut payload = Vec::<u8>::new();
111    payload.write_f32::<LittleEndian>(self.0)?;
112    ctx.compile_const(&payload, ValueKind::F32)
113  }
114}
115
116#[cfg(feature = "u8")]
117impl CompileConst for u8 {
118  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
119    let mut payload = Vec::<u8>::new();
120    payload.write_u8(*self)?;
121    ctx.compile_const(&payload, ValueKind::U8)
122  }
123}
124
125#[cfg(feature = "i8")]
126impl CompileConst for i8 {
127  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
128    let mut payload = Vec::<u8>::new();
129    payload.write_i8(*self)?;
130    ctx.compile_const(&payload, ValueKind::I8)
131  }
132}
133
134impl CompileConst for usize {
135  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
136    let mut payload = Vec::<u8>::new();
137    payload.write_u64::<LittleEndian>(*self as u64)?;
138    ctx.compile_const(&payload, ValueKind::Index)
139  }
140}
141
142macro_rules! impl_compile_const {
143  ($feature:literal, $t:tt) => {
144    paste! {
145      #[cfg(feature = $feature)]
146      impl CompileConst for $t {
147        fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
148          let mut payload = Vec::<u8>::new();
149          payload.[<write_ $t>]::<LittleEndian>(*self)?;
150          ctx.compile_const(&payload, ValueKind::[<$t:upper>])
151        }
152      }
153    }
154  };
155}
156
157#[cfg(feature = "u16")]
158impl_compile_const!("u16", u16);
159#[cfg(feature = "u32")]
160impl_compile_const!("u32", u32);
161#[cfg(feature = "u64")]
162impl_compile_const!("u64", u64);
163#[cfg(feature = "u128")]
164impl_compile_const!("u128", u128);
165#[cfg(feature = "i16")]
166impl_compile_const!("i16", i16);
167#[cfg(feature = "i32")]
168impl_compile_const!("i32", i32);
169#[cfg(feature = "i64")]
170impl_compile_const!("i64", i64);
171#[cfg(feature = "i128")]
172impl_compile_const!("i128", i128);
173
174#[cfg(feature = "bool")]
175impl CompileConst for bool {
176  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
177    let mut payload = Vec::<u8>::new();
178    payload.write_u8(if *self { 1 } else { 0 })?;
179    ctx.compile_const(&payload, ValueKind::Bool)
180  }
181}
182
183#[cfg(feature = "string")]
184impl CompileConst for String {
185  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
186    let mut payload = Vec::<u8>::new();
187    payload.write_u32::<LittleEndian>(self.len() as u32)?;
188    payload.extend_from_slice(self.as_bytes());
189    ctx.compile_const(&payload, ValueKind::String)
190  }
191}
192
193#[cfg(feature = "rational")]
194impl CompileConst for R64 {
195  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
196    let mut payload = Vec::<u8>::new();
197    payload.write_i64::<LittleEndian>(*self.numer())?;
198    payload.write_i64::<LittleEndian>(*self.denom())?;
199    ctx.compile_const(&payload, ValueKind::R64)
200  }
201}
202
203#[cfg(feature = "complex")]
204impl CompileConst for C64 {
205  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
206    let mut payload = Vec::<u8>::new();
207    payload.write_f64::<LittleEndian>(self.0.re)?;
208    payload.write_f64::<LittleEndian>(self.0.im)?;
209    ctx.compile_const(&payload, ValueKind::C64)
210  }
211}
212
213macro_rules! impl_compile_const_matrix {
214  ($matrix_type:ty) => {
215    impl<T> CompileConst for $matrix_type
216    where
217      T: ConstElem,
218    {
219      fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
220        let rows = self.nrows() as u32;
221        let cols = self.ncols() as u32;
222        let mut payload = Vec::<u8>::with_capacity((rows * cols) as usize * 8);
223
224        // write header: rows, cols
225        payload.write_u32::<LittleEndian>(rows)?;
226        payload.write_u32::<LittleEndian>(cols)?;
227
228        // write elements column-major
229        for c in 0..cols as usize {
230          for r in 0..rows as usize {
231            self[(r, c)].write_le(&mut payload);
232          }
233        }
234        let elem_vk = T::value_kind();
235        let mat_vk = ValueKind::Matrix(Box::new(elem_vk), vec![rows as usize, cols as usize]);
236        ctx.compile_const(&payload, mat_vk)
237      }
238    }
239  };
240}
241
242#[cfg(feature = "matrix1")]
243impl_compile_const_matrix!(na::Matrix1<T>);
244#[cfg(feature = "matrix2")]
245impl_compile_const_matrix!(na::Matrix2<T>);
246#[cfg(feature = "matrix3")]
247impl_compile_const_matrix!(na::Matrix3<T>);
248#[cfg(feature = "matrix4")]
249impl_compile_const_matrix!(na::Matrix4<T>);
250#[cfg(feature = "matrix2x3")]
251impl_compile_const_matrix!(na::Matrix2x3<T>);
252#[cfg(feature = "matrix3x2")]
253impl_compile_const_matrix!(na::Matrix3x2<T>);
254#[cfg(feature = "row_vector2")]
255impl_compile_const_matrix!(na::RowVector2<T>);
256#[cfg(feature = "row_vector3")]
257impl_compile_const_matrix!(na::RowVector3<T>);
258#[cfg(feature = "row_vector4")]
259impl_compile_const_matrix!(na::RowVector4<T>);
260#[cfg(feature = "vector2")]
261impl_compile_const_matrix!(na::Vector2<T>);
262#[cfg(feature = "vector3")]
263impl_compile_const_matrix!(na::Vector3<T>);
264#[cfg(feature = "vector4")]
265impl_compile_const_matrix!(na::Vector4<T>);
266#[cfg(feature = "matrixd")]
267impl_compile_const_matrix!(na::DMatrix<T>);
268#[cfg(feature = "vectord")]
269impl_compile_const_matrix!(na::DVector<T>);
270#[cfg(feature = "row_vectord")]
271impl_compile_const_matrix!(na::RowDVector<T>);
272
273#[cfg(feature = "matrix")]
274impl<T> CompileConst for Matrix<T> 
275where
276  T: CompileConst + ConstElem
277{
278  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
279    match self {
280      #[cfg(feature = "matrixd")]
281      Matrix::DMatrix(mat) => mat.borrow().compile_const(ctx),
282      #[cfg(feature = "vectord")]
283      Matrix::DVector(mat) => mat.borrow().compile_const(ctx),
284      #[cfg(feature = "row_vectord")]
285      Matrix::RowDVector(mat) => mat.borrow().compile_const(ctx),
286      #[cfg(feature = "matrix1")]
287      Matrix::Matrix1(mat) => mat.borrow().compile_const(ctx),
288      #[cfg(feature = "matrix2")]
289      Matrix::Matrix2(mat) => mat.borrow().compile_const(ctx),
290      #[cfg(feature = "matrix3")]
291      Matrix::Matrix3(mat) => mat.borrow().compile_const(ctx),
292      #[cfg(feature = "matrix4")]
293      Matrix::Matrix4(mat) => mat.borrow().compile_const(ctx),
294      #[cfg(feature = "matrix2x3")]
295      Matrix::Matrix2x3(mat) => mat.borrow().compile_const(ctx),
296      #[cfg(feature = "matrix3x2")]
297      Matrix::Matrix3x2(mat) => mat.borrow().compile_const(ctx),
298      #[cfg(feature = "row_vector2")]
299      Matrix::RowVector2(mat) => mat.borrow().compile_const(ctx),
300      #[cfg(feature = "row_vector3")]
301      Matrix::RowVector3(mat) => mat.borrow().compile_const(ctx),
302      #[cfg(feature = "row_vector4")]
303      Matrix::RowVector4(mat) => mat.borrow().compile_const(ctx),
304      #[cfg(feature = "vector2")]
305      Matrix::Vector2(mat) => mat.borrow().compile_const(ctx),
306      #[cfg(feature = "vector3")]
307      Matrix::Vector3(mat) => mat.borrow().compile_const(ctx),
308      #[cfg(feature = "vector4")]
309      Matrix::Vector4(mat) => mat.borrow().compile_const(ctx),
310    }
311  }
312}
313
314#[cfg(feature = "matrixd")]
315impl<T> CompileConst for Ref<DMatrix<T>> 
316where
317  T: CompileConst + ConstElem
318{
319  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
320    self.borrow().compile_const(ctx)
321  }
322}
323
324#[cfg(feature = "vectord")]
325impl<T> CompileConst for Ref<DVector<T>> 
326where
327  T: CompileConst + ConstElem
328{
329  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
330    self.borrow().compile_const(ctx)
331  }
332}
333
334#[cfg(feature = "row_vectord")]
335impl<T> CompileConst for Ref<RowDVector<T>> 
336where
337  T: CompileConst + ConstElem
338{
339  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
340    self.borrow().compile_const(ctx)
341  }
342}
343
344#[cfg(feature = "table")]
345impl CompileConst for MechTable {
346  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
347    let mut payload = Vec::<u8>::new();
348
349    // write the number of rows and columns
350    payload.write_u32::<LittleEndian>(self.rows as u32)?;
351    payload.write_u32::<LittleEndian>(self.cols as u32)?;
352
353    // write each column: (name hash, value kind, data column)
354    for (col_id, (vk, col_data)) in self.data.iter() {
355      // column name hash
356      payload.write_u64::<LittleEndian>(*col_id)?;
357      // value kind
358      let value_kind = col_data.index1d(0).kind();
359      value_kind.write_le(&mut payload);
360
361      // column data as matrix
362      col_data.write_le(&mut payload);
363    }
364
365    // Write the name strings into the payload
366    for (_col_id, col_name) in self.col_names.iter() {
367      col_name.write_le(&mut payload);
368    }
369    ctx.compile_const(&payload, self.kind())
370  }
371}
372
373#[cfg(feature = "record")]
374impl CompileConst for MechRecord {
375  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
376    let mut payload = Vec::<u8>::new();
377
378    // write the number of columns
379    payload.write_u32::<LittleEndian>(self.cols as u32)?;
380
381    // write each column: (name hash, value kind, data)
382    for (col_id, value) in self.data.iter() {
383      // column name hash
384      payload.write_u64::<LittleEndian>(*col_id)?;
385      // value kind
386      let value_kind = value.kind();
387      value_kind.write_le(&mut payload);
388      // value data
389      value.write_le(&mut payload);
390    }
391
392    // Write the field name strings into the payload
393    for (_col_id, col_name) in self.field_names.iter() {
394      col_name.write_le(&mut payload);
395    }
396    ctx.compile_const(&payload, self.kind())
397  }
398}
399
400#[cfg(feature = "enum")]
401impl CompileConst for MechEnum {
402  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
403    let mut payload = Vec::<u8>::new();
404
405    // write the enum id
406    payload.write_u64::<LittleEndian>(self.id)?;
407
408    // write the number of variants
409    payload.write_u32::<LittleEndian>(self.variants.len() as u32)?;
410
411    // write each variant: (variant id, has value, value data)
412    for (variant_id, variant_value) in self.variants.iter() {
413      // variant id
414      payload.write_u64::<LittleEndian>(*variant_id)?;
415      match variant_value {
416        Some(v) => {
417          // has value
418          payload.write_u8(1)?;
419          // value kind
420          let value_kind = v.kind();
421          value_kind.write_le(&mut payload);
422          // value data
423          v.write_le(&mut payload);
424        },
425        None => {
426          // has no value
427          payload.write_u8(0)?;
428        }
429      }
430    }
431    ctx.compile_const(&payload, ValueKind::Enum(self.id))
432  }
433}
434
435#[cfg(feature = "atom")]
436impl CompileConst for MechAtom {
437  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
438    let mut payload = Vec::<u8>::new();
439    payload.write_u64::<LittleEndian>(self.0)?;
440    ctx.compile_const(&payload, ValueKind::Atom(self.0))
441  }
442}
443
444// ConstElem Trait
445// ----------------------------------------------------------------------------
446
447pub trait ConstElem {
448  fn write_le(&self, out: &mut Vec<u8>);
449  fn value_kind() -> ValueKind;
450  fn align() -> u8 { 1 }
451}
452
453#[cfg(feature = "f64")]
454impl ConstElem for F64 {
455  fn write_le(&self, out: &mut Vec<u8>) {
456    out.write_f64::<LittleEndian>(self.0).expect("write f64");
457  }
458  fn value_kind() -> ValueKind { ValueKind::F64 }
459  fn align() -> u8 { 8 }
460}
461
462#[cfg(feature = "f32")]
463impl ConstElem for F32 {
464  fn write_le(&self, out: &mut Vec<u8>) {
465    out.write_f32::<LittleEndian>(self.0).expect("write f32");
466  }
467  fn value_kind() -> ValueKind { ValueKind::F32 }
468  fn align() -> u8 { 4 }
469} 
470
471macro_rules! impl_const_elem {
472  ($feature:literal, $t:ty, $align:expr) => {
473    paste!{
474      #[cfg(feature = $feature)]
475      impl ConstElem for $t {
476        fn write_le(&self, out: &mut Vec<u8>) {
477          out.[<write_ $t>]::<LittleEndian>(*self).expect(concat!("write ", stringify!($t)));
478        }
479        fn value_kind() -> ValueKind { ValueKind::[<$t:upper>] }
480        fn align() -> u8 { $align }
481      }
482    }
483  };
484}
485
486#[cfg(feature = "u16")]
487impl_const_elem!("u16", u16, 2);
488#[cfg(feature = "u32")]
489impl_const_elem!("u32", u32, 4);
490#[cfg(feature = "u64")]
491impl_const_elem!("u64", u64, 8);
492#[cfg(feature = "u128")]
493impl_const_elem!("u128", u128, 16);
494#[cfg(feature = "i16")]
495impl_const_elem!("i16", i16, 2);
496#[cfg(feature = "i32")]
497impl_const_elem!("i32", i32, 4);
498#[cfg(feature = "i64")]
499impl_const_elem!("i64", i64, 8);
500#[cfg(feature = "i128")]
501impl_const_elem!("i128", i128, 16);
502
503#[cfg(feature = "u8")]
504impl ConstElem for u8 {
505  fn write_le(&self, out: &mut Vec<u8>) {
506    out.write_u8(*self).expect("write u8");
507  }
508  fn value_kind() -> ValueKind { ValueKind::U8 }
509  fn align() -> u8 { 1 }
510} 
511
512#[cfg(feature = "i8")]
513impl ConstElem for i8 {
514  fn write_le(&self, out: &mut Vec<u8>) {
515    out.write_i8(*self).expect("write i8");
516  }
517  fn value_kind() -> ValueKind { ValueKind::I8 }
518  fn align() -> u8 { 1 }
519}
520
521#[cfg(feature = "rational")]
522impl ConstElem for R64 {
523  fn write_le(&self, out: &mut Vec<u8>) {
524    out.write_i64::<LittleEndian>(*self.numer()).expect("write rational numer");
525    out.write_i64::<LittleEndian>(*self.denom()).expect("write rational denom");
526  }
527  fn value_kind() -> ValueKind { ValueKind::R64 }
528  fn align() -> u8 { 16 }
529}
530
531#[cfg(feature = "complex")]
532impl ConstElem for C64 {
533  fn write_le(&self, out: &mut Vec<u8>) {
534    out.write_f64::<LittleEndian>(self.0.re).expect("write complex real");
535    out.write_f64::<LittleEndian>(self.0.im).expect("write complex imag");
536  }
537  fn value_kind() -> ValueKind { ValueKind::C64 }
538  fn align() -> u8 { 16 }
539}
540
541#[cfg(feature = "string")]
542impl ConstElem for String {
543  fn write_le(&self, out: &mut Vec<u8>) {
544    out.write_u32::<LittleEndian>(self.len() as u32).expect("write string length");
545    out.extend_from_slice(self.as_bytes());
546  }
547  fn value_kind() -> ValueKind { ValueKind::String }
548  fn align() -> u8 { 1 }
549}
550
551#[cfg(feature = "bool")]
552impl ConstElem for bool {
553  fn write_le(&self, out: &mut Vec<u8>) {
554    out.write_u8(if *self { 1 } else { 0 }).expect("write bool");
555  }
556  fn value_kind() -> ValueKind { ValueKind::Bool }
557  fn align() -> u8 { 1 }
558}
559
560impl ConstElem for usize {
561  fn write_le(&self, out: &mut Vec<u8>) {
562    out.write_u64::<LittleEndian>(*self as u64).expect("write usize");
563  }
564  fn value_kind() -> ValueKind { ValueKind::Index }
565  fn align() -> u8 { 8 }
566}
567
568macro_rules! impl_const_elem_matrix {
569  ($matrix_type:ty, $rows:expr, $cols:expr) => {
570    impl<T> ConstElem for $matrix_type
571    where
572      T: ConstElem
573    {
574      fn write_le(&self, out: &mut Vec<u8>) {
575        for c in 0..self.ncols() {
576          for r in 0..self.nrows() {
577            self[(r, c)].write_le(out);
578          }
579        }
580      }
581      fn value_kind() -> ValueKind { ValueKind::Matrix(Box::new(T::value_kind()), vec![$rows, $cols]) }
582      fn align() -> u8 { 8 }
583    }
584  };
585}
586
587#[cfg(feature = "matrix1")]
588impl_const_elem_matrix!(Matrix1<T>, 1, 1);
589#[cfg(feature = "matrix2")]
590impl_const_elem_matrix!(Matrix2<T>, 2, 2);
591#[cfg(feature = "matrix3")]
592impl_const_elem_matrix!(Matrix3<T>, 3, 3);
593#[cfg(feature = "matrix4")]
594impl_const_elem_matrix!(Matrix4<T>, 4, 4);
595#[cfg(feature = "matrix2x3")]
596impl_const_elem_matrix!(Matrix2x3<T>, 2, 3);
597#[cfg(feature = "matrix3x2")]
598impl_const_elem_matrix!(Matrix3x2<T>, 3, 2);
599#[cfg(feature = "row_vector2")]
600impl_const_elem_matrix!(RowVector2<T>, 1, 2);
601#[cfg(feature = "row_vector3")]
602impl_const_elem_matrix!(RowVector3<T>, 1, 3);
603#[cfg(feature = "row_vector4")]
604impl_const_elem_matrix!(RowVector4<T>, 1, 4);
605#[cfg(feature = "vector2")]
606impl_const_elem_matrix!(Vector2<T>, 2, 1);
607#[cfg(feature = "vector3")]
608impl_const_elem_matrix!(Vector3<T>, 3, 1);
609#[cfg(feature = "vector4")]
610impl_const_elem_matrix!(Vector4<T>, 4, 1);
611#[cfg(feature = "matrixd")]
612impl_const_elem_matrix!(DMatrix<T>, 0, 0);
613#[cfg(feature = "vectord")]
614impl_const_elem_matrix!(DVector<T>, 0, 1);
615#[cfg(feature = "row_vectord")]
616impl_const_elem_matrix!(RowDVector<T>, 1, 0);
617
618impl<T> ConstElem for Matrix<T> 
619where
620  T: ConstElem
621{
622  fn write_le(&self, out: &mut Vec<u8>) {
623    match self {
624      #[cfg(feature = "matrixd")]
625      Matrix::DMatrix(mat) => mat.borrow().write_le(out),
626      #[cfg(feature = "vectord")]
627      Matrix::DVector(mat) => mat.borrow().write_le(out),
628      #[cfg(feature = "row_vectord")]
629      Matrix::RowDVector(mat) => mat.borrow().write_le(out),
630      #[cfg(feature = "matrix1")]
631      Matrix::Matrix1(mat) => mat.borrow().write_le(out),
632      #[cfg(feature = "matrix2")]
633      Matrix::Matrix2(mat) => mat.borrow().write_le(out),
634      #[cfg(feature = "matrix3")]
635      Matrix::Matrix3(mat) => mat.borrow().write_le(out),
636      #[cfg(feature = "matrix4")]
637      Matrix::Matrix4(mat) => mat.borrow().write_le(out),
638      #[cfg(feature = "matrix2x3")]
639      Matrix::Matrix2x3(mat) => mat.borrow().write_le(out),
640      #[cfg(feature = "matrix3x2")]
641      Matrix::Matrix3x2(mat) => mat.borrow().write_le(out),
642      #[cfg(feature = "row_vector2")]
643      Matrix::RowVector2(mat) => mat.borrow().write_le(out),
644      #[cfg(feature = "row_vector3")]
645      Matrix::RowVector3(mat) => mat.borrow().write_le(out),
646      #[cfg(feature = "row_vector4")]
647      Matrix::RowVector4(mat) => mat.borrow().write_le(out),
648      #[cfg(feature = "vector2")]
649      Matrix::Vector2(mat) => mat.borrow().write_le(out),
650      #[cfg(feature = "vector3")]
651      Matrix::Vector3(mat) => mat.borrow().write_le(out),
652      #[cfg(feature = "vector4")]
653      Matrix::Vector4(mat) => mat.borrow().write_le(out),
654    }
655  }
656  fn value_kind() -> ValueKind { ValueKind::Matrix(Box::new(T::value_kind()), vec![0,0]) }
657  fn align() -> u8 { T::align() }
658}
659
660
661impl ConstElem for Value {
662  fn write_le(&self, out: &mut Vec<u8>) {
663    match self {
664      #[cfg(feature = "bool")]
665      Value::Bool(x) => x.borrow().write_le(out),
666      #[cfg(feature = "string")]
667      Value::String(x) => x.borrow().write_le(out),
668      #[cfg(feature = "u8")]
669      Value::U8(x) => x.borrow().write_le(out),
670      #[cfg(feature = "u16")]
671      Value::U16(x) => x.borrow().write_le(out),
672      #[cfg(feature = "u32")]
673      Value::U32(x) => x.borrow().write_le(out),
674      #[cfg(feature = "u64")]
675      Value::U64(x) => x.borrow().write_le(out),
676      #[cfg(feature = "u128")]
677      Value::U128(x) => x.borrow().write_le(out),
678      #[cfg(feature = "i8")]
679      Value::I8(x) => x.borrow().write_le(out),
680      #[cfg(feature = "i16")]
681      Value::I16(x) => x.borrow().write_le(out),
682      #[cfg(feature = "i32")]
683      Value::I32(x) => x.borrow().write_le(out),
684      #[cfg(feature = "i64")]
685      Value::I64(x) => x.borrow().write_le(out),
686      #[cfg(feature = "i128")]
687      Value::I128(x) => x.borrow().write_le(out),
688      #[cfg(feature = "f32")]
689      Value::F32(x) => x.borrow().write_le(out),
690      #[cfg(feature = "f64")]
691      Value::F64(x) => x.borrow().write_le(out),
692      #[cfg(feature = "rational")]
693      Value::R64(x) => x.borrow().write_le(out),
694      #[cfg(feature = "complex")]
695      Value::C64(x) => x.borrow().write_le(out),
696      _ => todo!(),
697    }
698  }
699  fn value_kind() -> ValueKind {ValueKind::Any}
700  fn align() -> u8 { 1 }
701}
702
703impl ConstElem for ValueKind {
704  fn write_le(&self, out: &mut Vec<u8>) {
705    match self {
706      ValueKind::U8 => out.write_u8(1).expect("write value kind"),
707      ValueKind::U16 => out.write_u8(2).expect("write value kind"),
708      ValueKind::U32 => out.write_u8(3).expect("write value kind"),
709      ValueKind::U64 => out.write_u8(4).expect("write value kind"),
710      ValueKind::U128 => out.write_u8(5).expect("write value kind"),
711      ValueKind::I8 => out.write_u8(6).expect("write value kind"),
712      ValueKind::I16 => out.write_u8(7).expect("write value kind"),
713      ValueKind::I32 => out.write_u8(8).expect("write value kind"),
714      ValueKind::I64 => out.write_u8(9).expect("write value kind"),
715      ValueKind::I128 => out.write_u8(10).expect("write value kind"),
716      ValueKind::F32 => out.write_u8(11).expect("write value kind"),
717      ValueKind::F64 => out.write_u8(12).expect("write value kind"),
718      ValueKind::C64 => out.write_u8(13).expect("write value kind"),
719      ValueKind::R64 => out.write_u8(14).expect("write value kind"),
720      ValueKind::String => out.write_u8(15).expect("write value kind"),
721      ValueKind::Bool => out.write_u8(16).expect("write value kind"),
722      ValueKind::Id => out.write_u8(17).expect("write value kind"),
723      ValueKind::Index => out.write_u8(18).expect("write value kind"),
724      ValueKind::Empty => out.write_u8(19).expect("write value kind"),
725      ValueKind::Any => out.write_u8(20).expect("write value kind"),
726      ValueKind::Matrix(elem_vk, dims) => {
727        out.write_u8(21).expect("write value kind");
728        elem_vk.write_le(out);
729        out.write_u32::<LittleEndian>(dims.len() as u32).expect("write matrix dims length");
730        for d in dims.iter() {
731          out.write_u32::<LittleEndian>(*d as u32).expect("write matrix dim");
732        }
733      },
734      ValueKind::Enum(id) => {
735        out.write_u8(22).expect("write value kind");
736        out.write_u64::<LittleEndian>(*id).expect("write enum id");
737      },
738      ValueKind::Record(fields) => {
739        out.write_u8(23).expect("write value kind");
740        out.write_u32::<LittleEndian>(fields.len() as u32).expect("write record fields length");
741        for (name, vk) in fields.iter() {
742          name.write_le(out);
743          vk.write_le(out);
744        }
745      },
746      ValueKind::Map(key_vk, val_vk) => {
747        out.write_u8(24).expect("write value kind");
748        key_vk.write_le(out);
749        val_vk.write_le(out);
750      },
751      ValueKind::Atom(id) => {
752        out.write_u8(25).expect("write value kind");
753        out.write_u64::<LittleEndian>(*id).expect("write atom id");
754      },
755      ValueKind::Table(fields, row_count) => {
756        out.write_u8(26).expect("write value kind");
757        out.write_u32::<LittleEndian>(fields.len() as u32).expect("write table fields length");
758        for (name, vk) in fields.iter() {
759          name.write_le(out);
760          vk.write_le(out);
761        }
762        out.write_u32::<LittleEndian>(*row_count as u32).expect("write table row count");
763      },
764      ValueKind::Tuple(vks) => {
765        out.write_u8(27).expect("write value kind");
766        out.write_u32::<LittleEndian>(vks.len() as u32).expect("write tuple length");
767        for vk in vks.iter() {
768          vk.write_le(out);
769        }
770      },
771      ValueKind::Reference(vk) => {
772        out.write_u8(28).expect("write value kind");
773        vk.write_le(out);
774      },
775      ValueKind::Set(vk, opt_size) => {
776        out.write_u8(29).expect("write value kind");
777        vk.write_le(out);
778        match opt_size {
779          Some(sz) => {
780            out.write_u8(1).expect("write set size flag");
781            out.write_u32::<LittleEndian>(*sz as u32).expect("write set size");
782          },
783          None => {
784            out.write_u8(0).expect("write set size flag");
785          }
786        }
787      },
788      ValueKind::Option(vk) => {
789        out.write_u8(30).expect("write value kind");
790        vk.write_le(out);
791      },
792    }
793  }
794  fn value_kind() -> ValueKind { ValueKind::Any }
795  fn align() -> u8 { 1 }
796}
797
798#[cfg(feature = "enum")]
799impl ConstElem for MechEnum {
800  fn write_le(&self, out: &mut Vec<u8>) {
801    // write the enum id
802    out.write_u64::<LittleEndian>(self.id).expect("write enum id");
803
804    // write the number of variants
805    out.write_u32::<LittleEndian>(self.variants.len() as u32).expect("write enum variants length");
806
807    // write each variant: (variant id, has value, value data)
808    for (variant_id, variant_value) in self.variants.iter() {
809      // variant id
810      out.write_u64::<LittleEndian>(*variant_id).expect("write enum variant id");
811      match variant_value {
812        Some(v) => {
813          // has value
814          out.write_u8(1).expect("write enum variant has value");
815          // value kind
816          let value_kind = v.kind();
817          value_kind.write_le(out);
818          // value data
819          v.write_le(out);
820        },
821        None => {
822          // has no value
823          out.write_u8(0).expect("write enum variant has no value");
824        }
825      }
826    }
827  }
828  fn value_kind() -> ValueKind { ValueKind::Enum(0) } // id 0 as placeholder
829  fn align() -> u8 { 8 }
830}