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