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)?;
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)?;
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, self.name()))
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.id())?;
409 self.name().write_le(&mut payload);
410 ctx.compile_const(&payload, ValueKind::Atom(self.id(), self.name().clone()))
411 }
412}
413
414#[cfg(feature = "set")]
415impl CompileConst for MechSet {
416 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
417 let mut payload = Vec::<u8>::new();
418 self.kind.write_le(&mut payload);
419 payload.write_u32::<LittleEndian>(self.num_elements as u32)?;
420 for element in &self.set {
421 element.write_le(&mut payload);
422 }
423 ctx.compile_const(&payload, self.kind())
424 }
425}
426
427#[cfg(feature = "tuple")]
428impl CompileConst for MechTuple {
429 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
430 let mut payload = Vec::<u8>::new();
431 self.value_kind().write_le(&mut payload);
432 payload.write_u32::<LittleEndian>(self.elements.len() as u32)?;
433 for elem in &self.elements {
434 elem.write_le(&mut payload);
435 }
436 ctx.compile_const(&payload, self.value_kind())
437 }
438}
439
440#[cfg(feature = "map")]
441impl CompileConst for MechMap {
442 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
443 let mut payload = Vec::<u8>::new();
444 self.key_kind.write_le(&mut payload);
445 self.value_kind.write_le(&mut payload);
446 payload.write_u32::<LittleEndian>(self.map.len() as u32)?;
447 for (key, value) in &self.map {
448 key.write_le(&mut payload);
449 value.write_le(&mut payload);
450 }
451 let map_vk = ValueKind::Map(Box::new(self.key_kind.clone()), Box::new(self.value_kind.clone()));
452 ctx.compile_const(&payload, map_vk)
453 }
454}
455
456pub trait ConstElem {
460 fn write_le(&self, out: &mut Vec<u8>);
461 fn from_le(bytes: &[u8]) -> Self;
462 fn value_kind(&self) -> ValueKind;
463 fn align() -> u8 { 1 }
464}
465
466macro_rules! impl_const_elem {
467 ($feature:literal, $t:ty, $align:expr) => {
468 paste!{
469 #[cfg(feature = $feature)]
470 impl ConstElem for $t {
471 fn write_le(&self, out: &mut Vec<u8>) {
472 out.[<write_ $t>]::<LittleEndian>(*self).expect(concat!("write ", stringify!($t)));
473 }
474 fn from_le(bytes: &[u8]) -> Self {
475 let mut rdr = std::io::Cursor::new(bytes);
476 rdr.[<read_ $t>]::<LittleEndian>().expect(concat!("read ", stringify!($t)))
477 }
478 fn value_kind(&self) -> ValueKind { ValueKind::[<$t:upper>] }
479 fn align() -> u8 { $align }
480 }
481 }
482 };
483}
484
485#[cfg(feature = "u16")]
486impl_const_elem!("u16", u16, 2);
487#[cfg(feature = "u32")]
488impl_const_elem!("u32", u32, 4);
489#[cfg(feature = "u64")]
490impl_const_elem!("u64", u64, 8);
491#[cfg(feature = "u128")]
492impl_const_elem!("u128", u128, 16);
493#[cfg(feature = "i16")]
494impl_const_elem!("i16", i16, 2);
495#[cfg(feature = "i32")]
496impl_const_elem!("i32", i32, 4);
497#[cfg(feature = "i64")]
498impl_const_elem!("i64", i64, 8);
499#[cfg(feature = "i128")]
500impl_const_elem!("i128", i128, 16);
501#[cfg(feature = "f32")]
502impl_const_elem!("f32", f32, 4);
503#[cfg(feature = "f64")]
504impl_const_elem!("f64", f64, 8);
505
506#[cfg(feature = "u8")]
507impl ConstElem for u8 {
508 fn write_le(&self, out: &mut Vec<u8>) {
509 out.write_u8(*self).expect("write u8");
510 }
511 fn from_le(bytes: &[u8]) -> Self {
512 bytes[0]
513 }
514 fn value_kind(&self) -> ValueKind { ValueKind::U8 }
515 fn align() -> u8 { 1 }
516}
517
518#[cfg(feature = "i8")]
519impl ConstElem for i8 {
520 fn write_le(&self, out: &mut Vec<u8>) {
521 out.write_i8(*self).expect("write i8");
522 }
523 fn from_le(bytes: &[u8]) -> Self {
524 bytes[0] as i8
525 }
526 fn value_kind(&self) -> ValueKind { ValueKind::I8 }
527 fn align() -> u8 { 1 }
528}
529
530#[cfg(feature = "rational")]
531impl ConstElem for R64 {
532 fn write_le(&self, out: &mut Vec<u8>) {
533 out.write_i64::<LittleEndian>(*self.numer()).expect("write rational numer");
534 out.write_i64::<LittleEndian>(*self.denom()).expect("write rational denom");
535 }
536 fn from_le(bytes: &[u8]) -> Self {
537 let numer = match bytes[0..8].try_into() {
538 Ok(arr) => i64::from_le_bytes(arr),
539 Err(_) => panic!("Failed to read numerator from bytes"),
540 };
541 let denom = match bytes[8..16].try_into() {
542 Ok(arr) => i64::from_le_bytes(arr),
543 Err(_) => panic!("Failed to read denominator from bytes"),
544 };
545 if denom == 0 {
546 panic!("Denominator cannot be zero");
547 }
548 R64::new(numer, denom)
549 }
550 fn value_kind(&self) -> ValueKind { ValueKind::R64 }
551 fn align() -> u8 { 16 }
552}
553
554#[cfg(feature = "complex")]
555impl ConstElem for C64 {
556 fn write_le(&self, out: &mut Vec<u8>) {
557 out.write_f64::<LittleEndian>(self.0.re).expect("write complex real");
558 out.write_f64::<LittleEndian>(self.0.im).expect("write complex imag");
559 }
560 fn from_le(bytes: &[u8]) -> Self {
561 let real = match bytes[0..8].try_into() {
562 Ok(arr) => f64::from_le_bytes(arr),
563 Err(_) => panic!("Failed to read real part from bytes"),
564 };
565 let imag = match bytes[8..16].try_into() {
566 Ok(arr) => f64::from_le_bytes(arr),
567 Err(_) => panic!("Failed to read imaginary part from bytes"),
568 };
569 C64::new(real, imag)
570 }
571 fn value_kind(&self) -> ValueKind { ValueKind::C64 }
572 fn align() -> u8 { 16 }
573}
574
575#[cfg(feature = "string")]
576impl ConstElem for String {
577 fn write_le(&self, out: &mut Vec<u8>) {
578 use byteorder::{LittleEndian, WriteBytesExt};
579 out.write_u32::<LittleEndian>(self.len() as u32).expect("write string length");
580 out.extend_from_slice(self.as_bytes());
581 }
582 fn from_le(bytes: &[u8]) -> Self {
583 use byteorder::{LittleEndian, ReadBytesExt};
584 use std::io::Cursor;
585 let mut cursor = Cursor::new(bytes);
586 let len = match cursor.read_u32::<LittleEndian>() {
588 Ok(n) => n as usize,
589 Err(_) => panic!("Failed to read string length from bytes"),
590 };
591 let start = cursor.position() as usize;
592 let end = start + len;
593 if end > bytes.len() {
594 panic!(
595 "String::from_le: declared length {} exceeds available bytes ({})",
596 len, bytes.len()
597 );
598 }
599 let str_bytes = &bytes[start..end];
600 match std::str::from_utf8(str_bytes) {
601 Ok(s) => s.to_string(),
602 Err(_) => panic!("Failed to convert bytes to UTF-8 string"),
603 }
604 }
605 fn value_kind(&self) -> ValueKind { ValueKind::String }
606 fn align() -> u8 { 1 }
607}
608
609#[cfg(feature = "bool")]
610impl ConstElem for bool {
611 fn write_le(&self, out: &mut Vec<u8>) {
612 out.write_u8(if *self { 1 } else { 0 }).expect("write bool");
613 }
614 fn from_le(bytes: &[u8]) -> Self {
615 bytes[0] != 0
616 }
617 fn value_kind(&self) -> ValueKind { ValueKind::Bool }
618 fn align() -> u8 { 1 }
619}
620
621impl ConstElem for usize {
622 fn write_le(&self, out: &mut Vec<u8>) {
623 out.write_u64::<LittleEndian>(*self as u64).expect("write usize");
624 }
625 fn from_le(bytes: &[u8]) -> Self {
626 let val = match bytes[0..8].try_into() {
627 Ok(arr) => u64::from_le_bytes(arr),
628 Err(_) => panic!("Failed to read usize from bytes"),
629 };
630 val as usize
631 }
632 fn value_kind(&self) -> ValueKind { ValueKind::Index }
633 fn align() -> u8 { 8 }
634}
635
636macro_rules! impl_const_elem_matrix {
637 ($matrix_type:ty) => {
638 impl<T> ConstElem for $matrix_type
639 where
640 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
641 {
642 fn write_le(&self, out: &mut Vec<u8>) {
643 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
644 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
645 for c in 0..self.ncols() {
646 for r in 0..self.nrows() {
647 self[(r, c)].write_le(out);
648 }
649 }
650 }
651 fn from_le(bytes: &[u8]) -> Self {
652 let mut cursor = Cursor::new(bytes);
653 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
654 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
655 let mut elements: Vec<T> = Vec::with_capacity(rows * cols);
656
657 for _c in 0..cols {
659 for _r in 0..rows {
660 let elem = T::from_le(&bytes[cursor.position() as usize..]);
661 let mut buf = Vec::new();
662 elem.write_le(&mut buf);
663 cursor.set_position(cursor.position() + buf.len() as u64);
664 elements.push(elem);
665 }
666 }
667 <$matrix_type>::from_row_slice(&elements)
670 }
671 fn value_kind(&self) -> ValueKind { self.value_kind() }
672 fn align() -> u8 { 8 }
673 }
674 };
675}
676
677#[cfg(feature = "matrixd")]
678impl<T> ConstElem for DMatrix<T>
679where
680 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
681{
682 fn write_le(&self, out: &mut Vec<u8>) {
683 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
684 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
685 for c in 0..self.ncols() {
686 for r in 0..self.nrows() {
687 self[(r, c)].write_le(out);
688 }
689 }
690 }
691 fn from_le(bytes: &[u8]) -> Self {
692 let mut cursor = Cursor::new(bytes);
693 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
694 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
695 let mut elements = Vec::with_capacity(rows * cols);
696 for _c in 0..cols {
698 for _r in 0..rows {
699 let elem = T::from_le(&bytes[cursor.position() as usize..]);
700 let mut buf = Vec::new();
701 elem.write_le(&mut buf);
702 cursor.set_position(cursor.position() + buf.len() as u64);
703 elements.push(elem);
704 }
705 }
706 DMatrix::from_vec(rows, cols, elements)
707 }
708 fn value_kind(&self) -> ValueKind { self.value_kind() }
709 fn align() -> u8 { 8 }
710}
711
712#[cfg(feature = "vectord")]
713impl<T> ConstElem for DVector<T>
714where
715 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
716{
717 fn write_le(&self, out: &mut Vec<u8>) {
718 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
719 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
720 for c in 0..self.ncols() {
721 for r in 0..self.nrows() {
722 self[(r, c)].write_le(out);
723 }
724 }
725 }
726 fn from_le(bytes: &[u8]) -> Self {
727 let mut cursor = Cursor::new(bytes);
728 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
729 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
730 let mut elements = Vec::with_capacity(rows * cols);
731 for _c in 0..cols {
733 for _r in 0..rows {
734 let elem = T::from_le(&bytes[cursor.position() as usize..]);
735 let mut buf = Vec::new();
736 elem.write_le(&mut buf);
737 cursor.set_position(cursor.position() + buf.len() as u64);
738 elements.push(elem);
739 }
740 }
741 DVector::from_vec(elements)
742 }
743 fn value_kind(&self) -> ValueKind { self.value_kind() }
744 fn align() -> u8 { 8 }
745}
746
747#[cfg(feature = "row_vectord")]
748impl<T> ConstElem for RowDVector<T>
749where
750 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
751{
752 fn write_le(&self, out: &mut Vec<u8>) {
753 out.write_u32::<LittleEndian>(self.nrows() as u32).unwrap();
754 out.write_u32::<LittleEndian>(self.ncols() as u32).unwrap();
755 for c in 0..self.ncols() {
756 for r in 0..self.nrows() {
757 self[(r, c)].write_le(out);
758 }
759 }
760 }
761 fn from_le(bytes: &[u8]) -> Self {
762 let mut cursor = Cursor::new(bytes);
763 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
764 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
765 let mut elements = Vec::with_capacity(rows * cols);
766 for _c in 0..cols {
768 for _r in 0..rows {
769 let elem = T::from_le(&bytes[cursor.position() as usize..]);
770 let mut buf = Vec::new();
771 elem.write_le(&mut buf);
772 cursor.set_position(cursor.position() + buf.len() as u64);
773 elements.push(elem);
774 }
775 }
776 RowDVector::from_vec(elements)
777 }
778 fn value_kind(&self) -> ValueKind { self.value_kind() }
779 fn align() -> u8 { 8 }
780}
781
782#[cfg(feature = "matrix1")]
783impl_const_elem_matrix!(Matrix1<T>);
784#[cfg(feature = "matrix2")]
785impl_const_elem_matrix!(Matrix2<T>);
786#[cfg(feature = "matrix3")]
787impl_const_elem_matrix!(Matrix3<T>);
788#[cfg(feature = "matrix4")]
789impl_const_elem_matrix!(Matrix4<T>);
790#[cfg(feature = "matrix2x3")]
791impl_const_elem_matrix!(Matrix2x3<T>);
792#[cfg(feature = "matrix3x2")]
793impl_const_elem_matrix!(Matrix3x2<T>);
794#[cfg(feature = "row_vector2")]
795impl_const_elem_matrix!(RowVector2<T>);
796#[cfg(feature = "row_vector3")]
797impl_const_elem_matrix!(RowVector3<T>);
798#[cfg(feature = "row_vector4")]
799impl_const_elem_matrix!(RowVector4<T>);
800#[cfg(feature = "vector2")]
801impl_const_elem_matrix!(Vector2<T>);
802#[cfg(feature = "vector3")]
803impl_const_elem_matrix!(Vector3<T>);
804#[cfg(feature = "vector4")]
805impl_const_elem_matrix!(Vector4<T>);
806
807#[cfg(feature = "matrix")]
808impl<T> ConstElem for Matrix<T>
809where
810 T: ConstElem + std::fmt::Debug + std::clone::Clone + PartialEq + 'static,
811{
812 fn write_le(&self, out: &mut Vec<u8>) {
813 match self {
814 #[cfg(feature = "matrixd")]
815 Matrix::DMatrix(mat) => mat.borrow().write_le(out),
816 #[cfg(feature = "vectord")]
817 Matrix::DVector(mat) => mat.borrow().write_le(out),
818 #[cfg(feature = "row_vectord")]
819 Matrix::RowDVector(mat) => mat.borrow().write_le(out),
820 #[cfg(feature = "matrix1")]
821 Matrix::Matrix1(mat) => mat.borrow().write_le(out),
822 #[cfg(feature = "matrix2")]
823 Matrix::Matrix2(mat) => mat.borrow().write_le(out),
824 #[cfg(feature = "matrix3")]
825 Matrix::Matrix3(mat) => mat.borrow().write_le(out),
826 #[cfg(feature = "matrix4")]
827 Matrix::Matrix4(mat) => mat.borrow().write_le(out),
828 #[cfg(feature = "matrix2x3")]
829 Matrix::Matrix2x3(mat) => mat.borrow().write_le(out),
830 #[cfg(feature = "matrix3x2")]
831 Matrix::Matrix3x2(mat) => mat.borrow().write_le(out),
832 #[cfg(feature = "row_vector2")]
833 Matrix::RowVector2(mat) => mat.borrow().write_le(out),
834 #[cfg(feature = "row_vector3")]
835 Matrix::RowVector3(mat) => mat.borrow().write_le(out),
836 #[cfg(feature = "row_vector4")]
837 Matrix::RowVector4(mat) => mat.borrow().write_le(out),
838 #[cfg(feature = "vector2")]
839 Matrix::Vector2(mat) => mat.borrow().write_le(out),
840 #[cfg(feature = "vector3")]
841 Matrix::Vector3(mat) => mat.borrow().write_le(out),
842 #[cfg(feature = "vector4")]
843 Matrix::Vector4(mat) => mat.borrow().write_le(out),
844 }
845 }
846 fn from_le(bytes: &[u8]) -> Self {
847 let mut cursor = Cursor::new(bytes);
848 let rows = cursor.read_u32::<LittleEndian>().unwrap() as usize;
849 let cols = cursor.read_u32::<LittleEndian>().unwrap() as usize;
850 let mut elements = Vec::with_capacity(rows * cols);
851 for _c in 0..cols {
853 for _r in 0..rows {
854 let elem = T::from_le(&bytes[cursor.position() as usize..]);
855 let mut buf = Vec::new();
856 elem.write_le(&mut buf);
857 cursor.set_position(cursor.position() + buf.len() as u64);
858 elements.push(elem);
859 }
860 }
861 if rows == 0 || cols == 0 {
862 panic!("Cannot create Matrix with zero rows or columns");
863 } else if cols == 1 {
864 match rows {
865 #[cfg(feature = "matrix1")]
866 1 => Matrix::Matrix1(Ref::new(Matrix1::from_vec(elements))),
867 #[cfg(all(feature = "matrixd", not(feature = "matrix1")))]
868 1 => Matrix::DMatrix(Ref::new(DMatrix::from_vec(1,1, elements))),
869 #[cfg(feature = "vector2")]
870 2 => Matrix::Vector2(Ref::new(Vector2::from_vec(elements))),
871 #[cfg(feature = "vector3")]
872 3 => Matrix::Vector3(Ref::new(Vector3::from_vec(elements))),
873 #[cfg(feature = "vector4")]
874 4 => Matrix::Vector4(Ref::new(Vector4::from_vec(elements))),
875 #[cfg(feature = "vectord")]
876 _ => Matrix::DVector(Ref::new(DVector::from_vec(elements))),
877 _ => panic!("No suitable Matrix variant for dimensions {}x{}", rows, cols),
878 }
879 } else if rows == 1 {
880 match cols {
881 #[cfg(feature = "row_vector2")]
882 2 => Matrix::RowVector2(Ref::new(RowVector2::from_vec(elements))),
883 #[cfg(feature = "row_vector3")]
884 3 => Matrix::RowVector3(Ref::new(RowVector3::from_vec(elements))),
885 #[cfg(feature = "row_vector4")]
886 4 => Matrix::RowVector4(Ref::new(RowVector4::from_vec(elements))),
887 #[cfg(feature = "row_vectord")]
888 _ => Matrix::RowDVector(Ref::new(RowDVector::from_vec(elements))),
889 _ => panic!("No suitable Matrix variant for dimensions {}x{}", rows, cols),
890 }
891 } else {
892 match (rows, cols) {
893 #[cfg(feature = "matrix1")]
894 (1, 1) => Matrix::Matrix1(Ref::new(Matrix1::from_row_slice(&elements))),
895 #[cfg(feature = "matrix2")]
896 (2, 2) => Matrix::Matrix2(Ref::new(Matrix2::from_row_slice(&elements))),
897 #[cfg(feature = "matrix3")]
898 (3, 3) => Matrix::Matrix3(Ref::new(Matrix3::from_row_slice(&elements))),
899 #[cfg(feature = "matrix4")]
900 (4, 4) => Matrix::Matrix4(Ref::new(Matrix4::from_row_slice(&elements))),
901 #[cfg(feature = "matrix2x3")]
902 (2, 3) => Matrix::Matrix2x3(Ref::new(Matrix2x3::from_row_slice(&elements))),
903 #[cfg(feature = "matrix3x2")]
904 (3, 2) => Matrix::Matrix3x2(Ref::new(Matrix3x2::from_row_slice(&elements))),
905 #[cfg(feature = "matrixd")]
906 _ => Matrix::DMatrix(Ref::new(DMatrix::from_vec(rows, cols, elements))),
907 _ => panic!("No suitable Matrix variant for dimensions {}x{}", rows, cols),
908 }
909 }
910 }
911 fn value_kind(&self) -> ValueKind { self.value_kind() }
912 fn align() -> u8 { T::align() }
913}
914
915
916impl ConstElem for Value {
917 fn write_le(&self, out: &mut Vec<u8>) {
918 self.kind().write_le(out);
920
921 match self {
923 Value::Empty => {
924 },
926 #[cfg(feature = "bool")]
927 Value::Bool(x) => x.borrow().write_le(out),
928 #[cfg(feature = "string")]
929 Value::String(x) => x.borrow().write_le(out),
930 #[cfg(feature = "u8")]
931 Value::U8(x) => x.borrow().write_le(out),
932 #[cfg(feature = "u16")]
933 Value::U16(x) => x.borrow().write_le(out),
934 #[cfg(feature = "u32")]
935 Value::U32(x) => x.borrow().write_le(out),
936 #[cfg(feature = "u64")]
937 Value::U64(x) => x.borrow().write_le(out),
938 #[cfg(feature = "u128")]
939 Value::U128(x) => x.borrow().write_le(out),
940 #[cfg(feature = "i8")]
941 Value::I8(x) => x.borrow().write_le(out),
942 #[cfg(feature = "i16")]
943 Value::I16(x) => x.borrow().write_le(out),
944 #[cfg(feature = "i32")]
945 Value::I32(x) => x.borrow().write_le(out),
946 #[cfg(feature = "i64")]
947 Value::I64(x) => x.borrow().write_le(out),
948 #[cfg(feature = "i128")]
949 Value::I128(x) => x.borrow().write_le(out),
950 #[cfg(feature = "f32")]
951 Value::F32(x) => x.borrow().write_le(out),
952 #[cfg(feature = "f64")]
953 Value::F64(x) => x.borrow().write_le(out),
954 #[cfg(feature = "rational")]
955 Value::R64(x) => x.borrow().write_le(out),
956 #[cfg(feature = "complex")]
957 Value::C64(x) => x.borrow().write_le(out),
958 #[cfg(feature = "set")]
959 Value::Set(x) => x.borrow().write_le(out),
960 _ => unimplemented!("write_le not implemented for this Value variant"),
961 }
962 }
963 fn from_le(bytes: &[u8]) -> Self {
964 let mut cursor = std::io::Cursor::new(bytes);
965
966 let kind = ValueKind::from_le(cursor.get_ref());
968
969 let mut kind_buf = Vec::new();
971 kind.write_le(&mut kind_buf);
972 let payload = &bytes[kind_buf.len()..];
973
974 match kind {
976 ValueKind::Empty => Value::Empty,
977 #[cfg(feature = "bool")]
978 ValueKind::Bool => Value::Bool(Ref::new(<bool as ConstElem>::from_le(payload))),
979 #[cfg(feature = "string")]
980 ValueKind::String => Value::String(Ref::new(<String as ConstElem>::from_le(payload))),
981 #[cfg(feature = "u8")]
982 ValueKind::U8 => Value::U8(Ref::new(<u8 as ConstElem>::from_le(payload))),
983 #[cfg(feature = "u16")]
984 ValueKind::U16 => Value::U16(Ref::new(<u16 as ConstElem>::from_le(payload))),
985 #[cfg(feature = "u32")]
986 ValueKind::U32 => Value::U32(Ref::new(<u32 as ConstElem>::from_le(payload))),
987 #[cfg(feature = "u64")]
988 ValueKind::U64 => Value::U64(Ref::new(<u64 as ConstElem>::from_le(payload))),
989 #[cfg(feature = "u128")]
990 ValueKind::U128 => Value::U128(Ref::new(<u128 as ConstElem>::from_le(payload))),
991 #[cfg(feature = "i8")]
992 ValueKind::I8 => Value::I8(Ref::new(<i8 as ConstElem>::from_le(payload))),
993 #[cfg(feature = "i16")]
994 ValueKind::I16 => Value::I16(Ref::new(<i16 as ConstElem>::from_le(payload))),
995 #[cfg(feature = "i32")]
996 ValueKind::I32 => Value::I32(Ref::new(<i32 as ConstElem>::from_le(payload))),
997 #[cfg(feature = "i64")]
998 ValueKind::I64 => Value::I64(Ref::new(<i64 as ConstElem>::from_le(payload))),
999 #[cfg(feature = "i128")]
1000 ValueKind::I128 => Value::I128(Ref::new(<i128 as ConstElem>::from_le(payload))),
1001 #[cfg(feature = "f32")]
1002 ValueKind::F32 => Value::F32(Ref::new(<f32 as ConstElem>::from_le(payload))),
1003 #[cfg(feature = "f64")]
1004 ValueKind::F64 => Value::F64(Ref::new(<f64 as ConstElem>::from_le(payload))),
1005 #[cfg(feature = "rational")]
1006 ValueKind::R64 => Value::R64(Ref::new(<R64 as ConstElem>::from_le(payload))),
1007 #[cfg(feature = "complex")]
1008 ValueKind::C64 => Value::C64(Ref::new(<C64 as ConstElem>::from_le(payload))),
1009 x => unimplemented!("from_le not implemented for this ValueKind variant: {:?}", x),
1010 }
1011 }
1012 fn value_kind(&self) -> ValueKind {
1013 self.value_kind()
1014 }
1015 fn align() -> u8 {
1016 1
1017 }
1018}
1019
1020impl ConstElem for ValueKind {
1021 fn write_le(&self, out: &mut Vec<u8>) {
1022 match self {
1023 ValueKind::U8 => out.write_u8(1).expect("write value kind"),
1024 ValueKind::U16 => out.write_u8(2).expect("write value kind"),
1025 ValueKind::U32 => out.write_u8(3).expect("write value kind"),
1026 ValueKind::U64 => out.write_u8(4).expect("write value kind"),
1027 ValueKind::U128 => out.write_u8(5).expect("write value kind"),
1028 ValueKind::I8 => out.write_u8(6).expect("write value kind"),
1029 ValueKind::I16 => out.write_u8(7).expect("write value kind"),
1030 ValueKind::I32 => out.write_u8(8).expect("write value kind"),
1031 ValueKind::I64 => out.write_u8(9).expect("write value kind"),
1032 ValueKind::I128 => out.write_u8(10).expect("write value kind"),
1033 ValueKind::F32 => out.write_u8(11).expect("write value kind"),
1034 ValueKind::F64 => out.write_u8(12).expect("write value kind"),
1035 ValueKind::C64 => out.write_u8(13).expect("write value kind"),
1036 ValueKind::R64 => out.write_u8(14).expect("write value kind"),
1037 ValueKind::String => out.write_u8(15).expect("write value kind"),
1038 ValueKind::Bool => out.write_u8(16).expect("write value kind"),
1039 ValueKind::Id => out.write_u8(17).expect("write value kind"),
1040 ValueKind::Index => out.write_u8(18).expect("write value kind"),
1041 ValueKind::Empty => out.write_u8(19).expect("write value kind"),
1042 ValueKind::Any => out.write_u8(20).expect("write value kind"),
1043 ValueKind::Matrix(elem_vk, dims) => {
1044 out.write_u8(21).expect("write value kind");
1045 elem_vk.write_le(out);
1046 out.write_u32::<LittleEndian>(dims.len() as u32).expect("write matrix dims length");
1047 for d in dims.iter() {
1048 out.write_u32::<LittleEndian>(*d as u32).expect("write matrix dim");
1049 }
1050 },
1051 ValueKind::Enum(id, name) => {
1052 out.write_u8(22).expect("write value kind");
1053 out.write_u64::<LittleEndian>(*id).expect("write enum id");
1054 name.write_le(out);
1055 },
1056 #[cfg(feature = "record")]
1057 ValueKind::Record(fields) => {
1058 out.write_u8(23).expect("write value kind");
1059 out.write_u32::<LittleEndian>(fields.len() as u32).expect("write record fields length");
1060 for (name, vk) in fields.iter() {
1061 name.write_le(out);
1062 vk.write_le(out);
1063 }
1064 },
1065 ValueKind::Map(key_vk, val_vk) => {
1066 out.write_u8(24).expect("write value kind");
1067 key_vk.write_le(out);
1068 val_vk.write_le(out);
1069 },
1070 ValueKind::Atom(id, name) => {
1071 out.write_u8(25).expect("write value kind");
1072 out.write_u64::<LittleEndian>(*id).expect("write atom id");
1073 name.write_le(out);
1074 },
1075 #[cfg(feature = "table")]
1076 ValueKind::Table(fields, row_count) => {
1077 out.write_u8(26).expect("write value kind");
1078 out.write_u32::<LittleEndian>(fields.len() as u32).expect("write table fields length");
1079 for (name, vk) in fields.iter() {
1080 name.write_le(out);
1081 vk.write_le(out);
1082 }
1083 out.write_u32::<LittleEndian>(*row_count as u32).expect("write table row count");
1084 },
1085 ValueKind::Tuple(vks) => {
1086 out.write_u8(27).expect("write value kind");
1087 out.write_u32::<LittleEndian>(vks.len() as u32).expect("write tuple length");
1088 for vk in vks.iter() {
1089 vk.write_le(out);
1090 }
1091 },
1092 ValueKind::Reference(vk) => {
1093 out.write_u8(28).expect("write value kind");
1094 vk.write_le(out);
1095 },
1096 ValueKind::Set(vk, opt_size) => {
1097 out.write_u8(29).expect("write value kind");
1098 vk.write_le(out);
1099 match opt_size {
1100 Some(sz) => {
1101 out.write_u8(1).expect("write set size flag");
1102 out.write_u32::<LittleEndian>(*sz as u32).expect("write set size");
1103 },
1104 None => {
1105 out.write_u8(0).expect("write set size flag");
1106 }
1107 }
1108 },
1109 ValueKind::Option(vk) => {
1110 out.write_u8(30).expect("write value kind");
1111 vk.write_le(out);
1112 },
1113 _ => unimplemented!("write_le not implemented for this ValueKind variant"),
1114 }
1115 }
1116 fn from_le(bytes: &[u8]) -> Self {
1117 let mut cursor = Cursor::new(bytes);
1118 let tag = cursor.read_u8().expect("read value kind tag");
1119
1120 match tag {
1121 0 => ValueKind::Empty,
1122 1 => ValueKind::U8,
1123 2 => ValueKind::U16,
1124 3 => ValueKind::U32,
1125 4 => ValueKind::U64,
1126 5 => ValueKind::U128,
1127 6 => ValueKind::I8,
1128 7 => ValueKind::I16,
1129 8 => ValueKind::I32,
1130 9 => ValueKind::I64,
1131 10 => ValueKind::I128,
1132 11 => ValueKind::F32,
1133 12 => ValueKind::F64,
1134 13 => ValueKind::C64,
1135 14 => ValueKind::R64,
1136 15 => ValueKind::String,
1137 16 => ValueKind::Bool,
1138 17 => ValueKind::Id,
1139 18 => ValueKind::Index,
1140 19 => ValueKind::Empty,
1141 20 => ValueKind::Any,
1142 #[cfg(feature = "matrix")]
1143 21 => {
1144 let elem_vk = ValueKind::from_le(&bytes[cursor.position() as usize..]);
1145 cursor.set_position(cursor.position() + 1); let dim_count = cursor.read_u32::<LittleEndian>().expect("read matrix dim count") as usize;
1147 let mut dims = Vec::with_capacity(dim_count);
1148 for _ in 0..dim_count {
1149 dims.push(cursor.read_u32::<LittleEndian>().expect("read matrix dim") as usize);
1150 }
1151 ValueKind::Matrix(Box::new(elem_vk), dims)
1152 }
1153 #[cfg(feature = "enum")]
1154 22 => {
1155 let id = cursor.read_u64::<LittleEndian>().expect("read enum id");
1156 let name = String::from_le(&bytes[cursor.position() as usize..]);
1157 ValueKind::Enum(id, name)
1158 }
1159 #[cfg(feature = "table")]
1160 26 => {
1161 let field_count = cursor.read_u32::<LittleEndian>().expect("read table fields length") as usize;
1162 let mut fields = Vec::with_capacity(field_count);
1163 for _ in 0..field_count {
1164 let name = String::from_le(&bytes[cursor.position() as usize..]);
1165 let mut buf = Vec::new();
1166 name.write_le(&mut buf);
1167 cursor.set_position(cursor.position() + buf.len() as u64);
1168 let vk = ValueKind::from_le(&bytes[cursor.position() as usize..]);
1169 let mut buf = Vec::new();
1170 vk.write_le(&mut buf);
1171 cursor.set_position(cursor.position() + buf.len() as u64);
1172 fields.push((name, vk));
1173 }
1174 let row_count = cursor.read_u32::<LittleEndian>().expect("read table row count") as usize;
1175 ValueKind::Table(fields, row_count)
1176 }
1177 #[cfg(feature = "set")]
1178 29 => {
1179 let elem_vk = ValueKind::from_le(&bytes[cursor.position() as usize..]);
1180 cursor.set_position(cursor.position() + 1);
1181 let size_flag = cursor.read_u8().expect("read set size flag");
1182 let opt_size = if size_flag != 0 {
1183 Some(cursor.read_u32::<LittleEndian>().expect("read set size") as usize)
1184 } else {
1185 None
1186 };
1187 ValueKind::Set(Box::new(elem_vk), opt_size)
1188 }
1189 x => unimplemented!("from_le not implemented for this ValueKind variant: {:?}", x),
1190 }
1191 }
1192 fn value_kind(&self) -> ValueKind { self.clone() }
1193 fn align() -> u8 { 1 }
1194}
1195
1196fn read_string_from_cursor(cursor: &mut std::io::Cursor<&[u8]>) -> Vec<u8> {
1198 let len = cursor.read_u32::<LittleEndian>().expect("read string len") as usize;
1199 let mut buf = vec![0u8; len];
1200 cursor.read_exact(&mut buf).expect("read string bytes");
1201 buf
1202}
1203
1204#[cfg(feature = "enum")]
1205impl ConstElem for MechEnum {
1206 fn write_le(&self, out: &mut Vec<u8>) {
1207 out.write_u64::<LittleEndian>(self.id).expect("write enum id");
1209
1210 out.write_u32::<LittleEndian>(self.variants.len() as u32).expect("write enum variants length");
1212
1213 for (variant_id, variant_value) in self.variants.iter() {
1215 out.write_u64::<LittleEndian>(*variant_id).expect("write enum variant id");
1217 match variant_value {
1218 Some(v) => {
1219 out.write_u8(1).expect("write enum variant has value");
1221 let value_kind = v.kind();
1223 value_kind.write_le(out);
1224 v.write_le(out);
1226 },
1227 None => {
1228 out.write_u8(0).expect("write enum variant has no value");
1230 }
1231 }
1232 }
1233 }
1234 fn from_le(_bytes: &[u8]) -> Self {
1235 unimplemented!("from_le not implemented for MechEnum")
1236 }
1237 fn value_kind(&self) -> ValueKind { ValueKind::Enum(0,"".to_string()) } fn align() -> u8 { 8 }
1239}
1240
1241#[cfg(feature = "table")]
1242impl ConstElem for MechTable {
1243 fn write_le(&self, out: &mut Vec<u8>) {
1244 self.value_kind().write_le(out);
1246 out.write_u32::<LittleEndian>(self.rows as u32).expect("write table rows");
1248 out.write_u32::<LittleEndian>(self.cols as u32).expect("write table cols");
1249 for (col_id, (vk, col_data)) in &self.data {
1251 out.write_u64::<LittleEndian>(*col_id).expect("write column id");
1253 vk.write_le(out);
1255 col_data.write_le(out);
1257 if let Some(name) = self.col_names.get(col_id) {
1259 name.write_le(out);
1260 } else {
1261 String::from("").write_le(out);
1262 }
1263 }
1264 }
1265 fn from_le(data: &[u8]) -> Self {
1266 use indexmap::IndexMap;
1267 let mut cursor = Cursor::new(data);
1268 let kind = ValueKind::from_le(cursor.get_ref());
1270 let mut buf = Vec::new();
1271 kind.write_le(&mut buf);
1272 cursor.set_position(buf.len() as u64);
1273
1274 let rows = cursor.read_u32::<LittleEndian>().expect("read rows") as usize;
1276 let cols = cursor.read_u32::<LittleEndian>().expect("read cols") as usize;
1277
1278 let mut data_map: IndexMap<u64, (ValueKind, Matrix<Value>)> = IndexMap::new();
1279 let mut col_names: HashMap<u64, String> = HashMap::new();
1280
1281 for _ in 0..cols {
1283 let col_id = cursor.read_u64::<LittleEndian>().expect("read column id");
1284
1285 let kind = ValueKind::from_le(&data[cursor.position() as usize..]);
1287 let mut tmp = Vec::new();
1288 kind.write_le(&mut tmp);
1289 cursor.set_position(cursor.position() + tmp.len() as u64);
1290
1291 let matrix = Matrix::<Value>::from_le(&data[cursor.position() as usize..]);
1293 let mut tmp = Vec::new();
1294 matrix.write_le(&mut tmp);
1295 cursor.set_position(cursor.position() + tmp.len() as u64);
1296
1297 let name = String::from_le(&data[cursor.position() as usize..]);
1299 let mut tmp = Vec::new();
1300 name.write_le(&mut tmp);
1301 cursor.set_position(cursor.position() + tmp.len() as u64);
1302
1303 data_map.insert(col_id, (kind, matrix));
1304 col_names.insert(col_id, name);
1305 }
1306
1307 MechTable { rows, cols, data: data_map, col_names }
1308 }
1309 fn value_kind(&self) -> ValueKind { self.kind() }
1310 fn align() -> u8 { 8 }
1311}
1312
1313#[cfg(feature = "table")]
1314impl CompileConst for MechTable {
1315 fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
1316 let mut payload = Vec::<u8>::new();
1317 self.value_kind().write_le(&mut payload);
1318 payload.write_u32::<LittleEndian>(self.rows as u32)?;
1319 payload.write_u32::<LittleEndian>(self.cols as u32)?;
1320 for (col_id, (vk, col_data)) in &self.data {
1321 payload.write_u64::<LittleEndian>(*col_id)?;
1322 vk.write_le(&mut payload);
1323 col_data.write_le(&mut payload);
1324
1325 if let Some(name) = self.col_names.get(col_id) {
1326 name.write_le(&mut payload);
1327 } else {
1328 String::from("").write_le(&mut payload);
1329 }
1330 }
1331 ctx.compile_const(&payload, self.value_kind())
1332 }
1333}
1334
1335#[cfg(feature = "set")]
1336impl ConstElem for MechSet {
1337 fn write_le(&self, out: &mut Vec<u8>) {
1338 self.kind.write_le(out);
1340 out.write_u32::<LittleEndian>(self.num_elements as u32)
1342 .expect("write set element count");
1343 for value in &self.set {
1345 value.write_le(out);
1346 }
1347 }
1348 fn from_le(data: &[u8]) -> Self {
1349 use indexmap::IndexSet;
1350 let mut cursor = Cursor::new(data);
1351 let start = cursor.position() as usize;
1353 let kind = ValueKind::from_le(&data[start..]);
1354 let mut kind_buf = Vec::new();
1356 kind.write_le(&mut kind_buf);
1357 cursor.set_position(start as u64 + kind_buf.len() as u64);
1358 let num_elements = cursor
1360 .read_u32::<LittleEndian>()
1361 .expect("read set element count") as usize;
1362 let mut set = IndexSet::with_capacity(num_elements);
1364 for _ in 0..num_elements {
1365 let pos = cursor.position() as usize;
1366 let value = Value::from_le(&data[pos..]);
1367 let mut tmp = Vec::new();
1369 value.write_le(&mut tmp);
1370 cursor.set_position(pos as u64 + tmp.len() as u64);
1371 set.insert(value);
1372 }
1373 Self { kind, num_elements, set }
1374 }
1375 fn value_kind(&self) -> ValueKind { self.kind.clone() }
1376 fn align() -> u8 { 8 }
1377}
1378
1379#[cfg(feature = "tuple")]
1380impl ConstElem for MechTuple {
1381 fn write_le(&self, out: &mut Vec<u8>) {
1382 self.value_kind().write_le(out);
1383 out.write_u32::<LittleEndian>(self.elements.len() as u32)
1384 .expect("write tuple element count");
1385 for elem in &self.elements {
1386 elem.write_le(out);
1387 }
1388 }
1389 fn from_le(data: &[u8]) -> Self {
1390 let mut cursor = Cursor::new(data);
1391 let start = cursor.position() as usize;
1393 let kind = ValueKind::from_le(&data[start..]);
1394 let mut kind_buf = Vec::new();
1396 kind.write_le(&mut kind_buf);
1397 cursor.set_position(start as u64 + kind_buf.len() as u64);
1398 let num_elements = cursor
1400 .read_u32::<LittleEndian>()
1401 .expect("read tuple element count") as usize;
1402 let mut elements: Vec<Box<Value>> = Vec::with_capacity(num_elements);
1404 for _ in 0..num_elements {
1405 let pos = cursor.position() as usize;
1406 let value = Value::from_le(&data[pos..]);
1407 let mut tmp = Vec::new();
1409 value.write_le(&mut tmp);
1410 cursor.set_position(pos as u64 + tmp.len() as u64);
1411 elements.push(Box::new(value));
1412 }
1413 Self { elements }
1414 }
1415 fn value_kind(&self) -> ValueKind {
1416 ValueKind::Tuple(
1417 self.elements
1418 .iter()
1419 .map(|v| v.value_kind())
1420 .collect::<Vec<_>>()
1421 )
1422 }
1423 fn align() -> u8 { 8 }
1424}